{
  "version": 3,
  "sources": ["../../src/index.ts", "../../src/lexer.ts", "../../src/levenshtein.ts", "../../src/ast.ts", "../../src/parser.ts", "../../src/operators.ts", "../../src/codegen.ts", "../../src/stages.ts", "../../src/match-translation.ts", "../../src/union-translation.ts", "../../src/stream-methods.ts", "../../src/lookup-translation.ts", "../../src/facet-translation.ts", "../../src/stage-validation.ts", "../../src/out-translation.ts", "../../src/system-stage-translation.ts", "../../src/pipeline.ts"],
  "sourcesContent": ["import { Parser, ParseError, FunctionInputError, type FunctionInputResult } from \"./parser.ts\";\nimport {\n  generate,\n  generateUpdateFilter,\n  generateWithCtx,\n  tryRewriteMutatorCall,\n  CodegenError,\n  EMPTY_CTX,\n  UnknownIdentifierError,\n  withBindings,\n  isOpaqueBsonValue,\n  type GenerateCtx,\n} from \"./codegen.ts\";\nimport { isPipelineAst, generatePipeline, generateImplicitPipeline } from \"./pipeline.ts\";\nimport { translateMatchBody, mergeTranslatedQuery } from \"./match-translation.ts\";\nimport { lookupStage } from \"./stages.ts\";\nimport { LexError } from \"./lexer.ts\";\nimport { containsLookupCall } from \"./lookup-translation.ts\";\nimport { containsUnionPush, detectUnionPush } from \"./union-translation.ts\";\nimport { containsOutAssign } from \"./out-translation.ts\";\nimport { isSystemStageCall } from \"./system-stage-translation.ts\";\nimport type { Program, Expr, Pipeline } from \"./ast.ts\";\n\n// Re-exported so users can `import { FunctionInputError } from \"@koresar/jsmql\"`\n// even though the class itself lives in parser.ts (where it is thrown).\nexport { FunctionInputError };\n\nexport type ValidationError = { message: string; pos: number; code: \"SYNTAX_ERROR\" | \"CODEGEN_ERROR\" };\n\nexport type ValidationResult = { valid: boolean; errors: ValidationError[] };\n\n// Raised by the template-tag invocation of `jsmql` when an interpolated value\n// cannot be safely embedded as a JSON literal. Covers the three cases\n// JSON.stringify mishandles: values it returns `undefined` for (functions,\n// Symbols, plain `undefined`), the non-finite numbers it silently coerces to\n// `null` (NaN/Infinity/-Infinity), and values it throws on (BigInt, circular\n// references). Surfacing these as a dedicated error means the caller learns\n// about the problem at interpolation time instead of getting a confusing parse\n// error or silent data loss downstream.\n//\n// `slot` is the 1-based template-tag interpolation index for the template-tag\n// path. `key` is the param-binding name for the `jsmql.compile()` call path.\n// Exactly one of the two is set depending on which surface raised the error.\nexport class JsmqlInterpolationError extends Error {\n  readonly slot: number;\n  readonly key?: string;\n  constructor(message: string, slot: number, key?: string) {\n    super(message);\n    this.name = \"JsmqlInterpolationError\";\n    this.slot = slot;\n    this.key = key;\n  }\n}\n\n// Accept any callable shape: the canonical idiom is `($) => \u2026` (one\n// parameter named `$`, used as the document-context placeholder), but `()\n// => \u2026` and `(doc) => \u2026` are equally valid \u2014 the parameter list is\n// stripped at extraction time. `any` for the `$` parameter lets users\n// write unannotated `$` and still get IDE autocomplete (`$.foo.bar`)\n// without `noImplicitAny` complaining.\n//\n// The optional second parameter is types-only: it gives users a destructure\n// site for escape-hatch operators (`($, { $dateDiff }) => $dateDiff(\u2026)`) so\n// IDEs don't flag `$dateDiff` as an unknown identifier. The parameter list\n// is stripped before the parser runs, so this never reaches the runtime.\nexport type JsmqlOps = Record<`$${string}`, (...args: any[]) => any>;\ntype JsmqlFn = ($: any, ops: JsmqlOps) => unknown;\nexport type JsmqlInput = string | JsmqlFn;\n\n// Function-form parameter binding (used by `jsmql.compile`). The arrow's\n// first slot is a destructure pattern that names the bindings; the same names\n// must appear as keys on the params object passed at call time. The `$` and\n// ops-hint slots remain optional and order-disambiguated by shape \u2014 see\n// `Parser.parseParameterList` for the rule and docs/LANGUAGE.md for the\n// user-facing reference.\n//\n// `$` and `ops` are declared as required (not `?:`) so that users who\n// explicitly annotate them with a destructure type \u2014 `({ $match }: JsmqlOps)`\n// \u2014 get clean type inference. TypeScript already lets users omit trailing\n// parameters when assigning to a function type, so `(params) => \u2026` and\n// `(params, $) => \u2026` still work; the parser also strips the parameter list\n// at extraction time, so the runtime never sees any of these declarations.\ntype JsmqlCompileFn<P> = (params: P, $: any, ops: JsmqlOps) => unknown;\n\n// `jsmql()` returns either a single compiled MQL expression object, or \u2014 when\n// the input is a top-level aggregation pipeline `[ { $stage: ... }, ... ]` \u2014\n// the corresponding stage array. The union is widened from the historical\n// `object` to make pipeline mode visible in the type. Both runtime values are\n// objects, so existing call sites keep type-checking.\nexport type JsmqlOutput = object | object[];\n\n// `jsmql` has three call shapes \u2014 string, arrow function, and template tag \u2014\n// dispatched on the first argument. The template-tag form is detected by the\n// standard \"frozen `TemplateStringsArray`\" discriminator: an Array whose `raw`\n// property is also an Array. The current `JsmqlInput` excludes arrays, so this\n// check collides with nothing in the typed surface. Note: if `JsmqlInput` is\n// ever widened to include plain pipeline arrays, the discriminator must still\n// run first \u2014 `Array.isArray` alone would no longer disambiguate.\nfunction isTemplateStringsArray(x: unknown): x is TemplateStringsArray {\n  return Array.isArray(x) && Array.isArray((x as { raw?: unknown }).raw);\n}\n\n/** An arrow-function input's source text (its `.toString()`), trimmed. */\nfunction fnSource(fn: (...args: never[]) => unknown): string {\n  return Function.prototype.toString.call(fn).trim();\n}\n\n/**\n * Parse arrow-function source and run `body` on the `(program, bindings)`\n * result, routing any error \u2014 from the parse OR from whatever `body` does \u2014 through\n * `augmentForFunctionInput`, so closure-reference / param-binding errors pick up\n * the template-tag hint regardless of which entry point triggered them. The\n * one-shot (`jsmql()`) and `validate` paths wrap parse + lower together; `compile`\n * uses it parse-only (its lowering happens later, inside the returned closure).\n */\nfunction withFunctionInput<T>(src: string, body: (parsed: FunctionInputResult) => T): T {\n  try {\n    return body(new Parser(src).parseFunctionInput());\n  } catch (err) {\n    throw augmentForFunctionInput(err);\n  }\n}\n\n/**\n * Single shared dispatcher for every public entry point that accepts the three\n * call shapes (string, arrow, template tag). The caller supplies its own\n * `lower` (Filter for `jsmql()`, expression for `jsmql.expr()`) and an\n * `apiName` for error messages \u2014 everything else (parsing, function-input\n * binding-rejection, function-input error augmentation, type guard) stays in\n * one place. Less code = better DX inside the codebase too.\n */\nfunction dispatchInput(\n  input: JsmqlInput | TemplateStringsArray,\n  values: unknown[],\n  apiName: string,\n  lower: (program: Program, ctx: GenerateCtx) => JsmqlOutput,\n): JsmqlOutput {\n  if (isTemplateStringsArray(input)) {\n    // Opaque BSON instances (Date, RegExp, Buffer, ObjectId) can't be embedded\n    // as JSON literals \u2014 `JSON.stringify(new Date(...))` yields an ISO string,\n    // `JSON.stringify(/x/)` yields `\"{}\"`. Route them through a synthesized\n    // ParamRef binding instead, so the value reaches MQL output as-is. Plain\n    // JSON-shaped values still go through `JSON.stringify` (unchanged).\n    let src = \"\";\n    const opaqueBindings = new Map<string, unknown>();\n    for (let i = 0; i < input.length; i++) {\n      src += input[i];\n      if (i < values.length) {\n        src += stringifyInterpolation(values[i], i + 1, opaqueBindings);\n      }\n    }\n    const ctx = opaqueBindings.size > 0 ? withBindings(EMPTY_CTX, opaqueBindings) : EMPTY_CTX;\n    return lower(new Parser(src).parse(), ctx);\n  }\n  if (typeof input === \"function\") {\n    // The wrapper covers both parsing AND lowering: `augmentForFunctionInput`\n    // must also fire when codegen throws an `UnknownIdentifierError` (closure\n    // ref) mid-lowering, not only when the arrow itself fails to parse.\n    return withFunctionInput(fnSource(input), ({ program, bindings }) => {\n      if (bindings.length > 0) {\n        throw new FunctionInputError(\n          `${apiName}() in its one-shot form does not accept a parameter-bindings destructure. ` +\n            \"Use `jsmql.compile(fn)(params)` to supply values to a parameterised query, \" +\n            \"or remove the destructure pattern from the arrow's first slot.\",\n        );\n      }\n      return lower(program, EMPTY_CTX);\n    });\n  }\n  if (typeof input === \"string\") {\n    return lower(new Parser(input).parse(), EMPTY_CTX);\n  }\n  // Polymorphism widens the runtime input space \u2014 without this guard, a\n  // wrong-typed call (e.g. `jsmql(42)`, `jsmql({})`) would crash deep inside\n  // the parser with a confusing message. DX priority #1 says vague errors are\n  // not acceptable, so name the contract here.\n  const ty = input === null ? \"null\" : typeof input;\n  throw new TypeError(`${apiName}() expects a string, an arrow function, or a template literal \u2014 got ${ty}.`);\n}\n\nfunction jsmqlDispatch(input: JsmqlInput): JsmqlOutput;\nfunction jsmqlDispatch(strings: TemplateStringsArray, ...values: unknown[]): JsmqlOutput;\nfunction jsmqlDispatch(input: JsmqlInput | TemplateStringsArray, ...values: unknown[]): JsmqlOutput {\n  return dispatchInput(input, values, \"jsmql\", lowerWithCtx);\n}\n\n/**\n * `jsmql.expr(input)` \u2014 compile a partial / \"unfinished\" expression in\n * aggregation-expression form, the shape used inside Pipeline stage bodies\n * (`$project`, `$addFields`, `$group`, \u2026) and as the second argument to\n * `db.coll.updateOne(filter, update)` when the update is a update op.\n *\n * Differs from `jsmql()` only in the no-`;` bare-expression branch: instead of\n * Filter dispatch (`{ $expr: ... }` wrap for non-predicates), the expression\n * lowers directly to its aggregation-expression form. `;`-separated input is\n * still a Pipeline, update op chains still produce `$set`/`$unset`, and array-\n * literal Pipelines still pass through \u2014 the three other branches are shared\n * with `jsmql()` via `lowerProgram`. Same three input shapes as `jsmql()`.\n */\nfunction exprDispatch(input: JsmqlInput): JsmqlOutput;\nfunction exprDispatch(strings: TemplateStringsArray, ...values: unknown[]): JsmqlOutput;\nfunction exprDispatch(input: JsmqlInput | TemplateStringsArray, ...values: unknown[]): JsmqlOutput {\n  return dispatchInput(input, values, \"jsmql.expr\", lowerExprWithCtx);\n}\n\n/**\n * `jsmql.filter(input)` \u2014 compile to a Filter document only.\n *\n * Same three input shapes as `jsmql()` (string / arrow / template tag), but\n * rejects any input that would lower to a Pipeline. Use this when the call\n * site is `db.coll.find(filter)` (or `deleteOne` / `countDocuments` / etc.)\n * and you want a compile-time guarantee that you won't accidentally hand the\n * driver a stage array. `jsmql()` is the polymorphic counterpart \u2014 call it\n * when the same source string might legitimately produce either shape.\n *\n * Pipeline-shaped inputs that throw here: `;`-separated statements, update-op\n * chains (`$.x = \u2026`, `delete $.x`), top-level stage calls (`$match(...)`),\n * single-key stage-object literals (`{ $match: ... }`), and array-literal\n * Pipelines (`[{ $stage: ... }, ...]`). Each error names the shape it found\n * and suggests the right call (`jsmql.pipeline()`, `jsmql.update()`,\n * `jsmql()`).\n */\nfunction filterDispatch(input: JsmqlInput): object;\nfunction filterDispatch(strings: TemplateStringsArray, ...values: unknown[]): object;\nfunction filterDispatch(input: JsmqlInput | TemplateStringsArray, ...values: unknown[]): object {\n  return dispatchInput(input, values, \"jsmql.filter\", lowerFilterStrict) as object;\n}\n\n/**\n * `jsmql.pipeline(input)` \u2014 compile to a Pipeline (stage array) only.\n *\n * Same three input shapes as `jsmql()`, but rejects any bare expression that\n * would lower to a Filter document. Use this when the call site is\n * `db.coll.aggregate(pipeline)` and you want a compile-time guarantee that\n * you won't accidentally hand the driver a single document where it expects\n * a stage array. Accepts every shape that already produces a Pipeline through\n * `jsmql()`:\n *\n *   - `;`-separated statements\n *   - a single top-level stage call (`$match(...)`) \u2014 auto-wraps to one stage\n *   - a single stage-object literal (`{ $match: ... }`) \u2014 auto-wraps too\n *   - update-op chains (`$.x = \u2026`) \u2014 compile to `$set` / `$unset` stages\n *   - array-literal Pipelines (`[{ $stage: ... }, ...]`)\n *\n * A bare expression like `$.age > 18` throws \u2014 the error suggests `jsmql.filter()`\n * if you wanted a Filter, or wrapping in `$match(...)` to make it a Pipeline.\n */\nfunction pipelineDispatch(input: JsmqlInput): object[];\nfunction pipelineDispatch(strings: TemplateStringsArray, ...values: unknown[]): object[];\nfunction pipelineDispatch(input: JsmqlInput | TemplateStringsArray, ...values: unknown[]): object[] {\n  return dispatchInput(input, values, \"jsmql.pipeline\", lowerPipelineStrict) as object[];\n}\n\n/**\n * `jsmql.update(input)` \u2014 compile to an aggregation-pipeline update (the\n * second argument to `db.coll.updateOne(filter, update)` /\n * `db.coll.updateMany(filter, update)` in its array form, called an\n * `UpdateFilter` in the Node.js MongoDB driver's typings).\n *\n * The shorter public name (`update` rather than `updateFilter`) avoids the\n * trap where developers read \"filter\" as the *query* document \u2014 the first\n * argument to `updateOne(filter, update)` \u2014 and reach for this when they\n * meant `jsmql.filter()`. The MongoDB driver type stays `UpdateFilter<T>`;\n * we just don't repeat the confusing half of its name in the function.\n *\n * Output is always a stage array, never the legacy bare-document update form\n * \u2014 that form silently treats RHS expressions as object literals, which is\n * exactly the kind of footgun this entry point exists to avoid. Passing this\n * to the driver guarantees that expressions like `$.name.toUpperCase()`\n * evaluate server-side instead of landing in the document as the literal\n * object `{ $toUpper: \"$name\" }`.\n *\n * Accepts the same Pipeline-shaped inputs as `jsmql.pipeline()`, but\n * additionally rejects any stage outside MongoDB's update-pipeline whitelist\n * (`$addFields`, `$set`, `$project`, `$unset`, `$replaceRoot`, `$replaceWith`).\n * If you write `$match` or `$sort` inside an update pipeline, MongoDB rejects\n * it at runtime with a generic error; this entry point catches it at compile\n * time and names the offending stage.\n */\nfunction updateDispatch(input: JsmqlInput): object[];\nfunction updateDispatch(strings: TemplateStringsArray, ...values: unknown[]): object[];\nfunction updateDispatch(input: JsmqlInput | TemplateStringsArray, ...values: unknown[]): object[] {\n  return dispatchInput(input, values, \"jsmql.update\", lowerUpdateStrict) as object[];\n}\n\n/**\n * Compile a parameterised arrow function to a reusable MQL builder.\n *\n * The arrow's first slot is a destructure pattern naming the bindings: a\n * `Record<string, JsonValue>` whose keys must be supplied as the params\n * object at call time. The returned function does no parsing on each\n * invocation \u2014 it walks the cached AST with the bound values substituted in\n * place of `ParamRef` nodes, emitting an inline MQL literal for each.\n *\n * The MQL output shape matches the template-tag form: each binding value\n * appears as a JSON literal, never wrapped in `$let`. This makes parameter\n * bindings compose uniformly across expression mode, pipeline mode, and\n * sub-pipelines (`$lookup`, `$unionWith`, `$facet`), and avoids `$$name`\n * collisions with lambda parameters.\n *\n * The input may also be a **string** containing the arrow source text \u2014 e.g.\n * `jsmql.compile(\"({ minAge }, $) => $.age > minAge\")`. This is useful when\n * the query is stored externally (config, file, database) and the caller\n * still wants the parse-once-bind-many semantics. The destructure pattern is\n * the only parameter-declaration mechanism for both call shapes; placeholder\n * syntaxes like `${name}` are deliberately not supported (they would break\n * the strict-JS-subset rule and collide with real template literals).\n */\nfunction compileFunction<P extends Record<string, unknown>>(fn: JsmqlCompileFn<P>): (params: P) => JsmqlOutput;\nfunction compileFunction(src: string): (params: Record<string, unknown>) => JsmqlOutput;\nfunction compileFunction<P extends Record<string, unknown>>(\n  input: JsmqlCompileFn<P> | string,\n): (params: P) => JsmqlOutput {\n  let src: string;\n  if (typeof input === \"function\") {\n    src = fnSource(input);\n  } else if (typeof input === \"string\") {\n    src = input.trim();\n  } else {\n    const ty = input === null ? \"null\" : typeof input;\n    throw new TypeError(`jsmql.compile() expects an arrow function or a string containing one \u2014 got ${ty}.`);\n  }\n  // Parse-only: lowering happens later, inside the returned closure (it needs\n  // the per-call params), so only the parse runs under the function-input augment.\n  const { program, bindings } = withFunctionInput(src, (r) => r);\n  return (params: P): JsmqlOutput => {\n    const resolved = new Map<string, unknown>();\n    for (const b of bindings) {\n      if (!Object.prototype.hasOwnProperty.call(params, b.key)) {\n        // The body refers to `b.name`; the user's missing key is `b.key`. When\n        // aliased, mention both so the user can find either.\n        const expected = b.key === b.name ? b.key : `${b.key}' (bound to '${b.name}' in the function body)`;\n        throw new UnknownIdentifierError(expected);\n      }\n      const value = (params as Record<string, unknown>)[b.key];\n      validateInterpolatable(value, 0, b.key);\n      resolved.set(b.name, value);\n    }\n    const ctx = withBindings(EMPTY_CTX, resolved);\n    return lowerWithCtx(program, ctx);\n  };\n}\n\n/**\n * Parse-and-validate any input shape `jsmql()` or `jsmql.compile()` accepts.\n * Returns a `ValidationResult` with structured errors instead of throwing,\n * so callers can drive editor tooling, form validation, and similar use cases.\n *\n * The overload set is the union of `jsmql.compile`'s and `jsmql()`'s \u2014 the\n * compile-form arrow comes first so IDEs contextually type `({ minAge }, $)`\n * against `(params: P, $: any, ops: JsmqlOps)` rather than the one-shot\n * `($: any, ops: JsmqlOps)` shape (which would mis-type the second slot as\n * `JsmqlOps`).\n */\nfunction validateInput<P extends Record<string, unknown>>(fn: JsmqlCompileFn<P>): ValidationResult;\nfunction validateInput(input: JsmqlInput): ValidationResult;\nfunction validateInput(strings: TemplateStringsArray, ...values: unknown[]): ValidationResult;\nfunction validateInput(\n  // The implementation signature must be assignable from every overload, so it\n  // widens to include the compile-form arrow shape (`JsmqlCompileFn<any>`)\n  // alongside `JsmqlInput` and the template-tag array. The compile-form arrow\n  // doesn't fit `JsmqlInput`'s `JsmqlFn = ($: any, ops: JsmqlOps) => unknown`\n  // shape because its first slot is the params destructure, not `$`.\n  input: JsmqlInput | TemplateStringsArray | JsmqlCompileFn<any>,\n  ...values: unknown[]\n): ValidationResult {\n  try {\n    if (isTemplateStringsArray(input)) {\n      jsmql(input, ...values);\n    } else if (typeof input === \"function\") {\n      // Inline the function-input path here (instead of delegating to\n      // `jsmql(input)`) so compile-form arrows \u2014 those carrying a params\n      // destructure \u2014 are accepted for validation. `jsmqlDispatch` rejects\n      // them outright in the one-shot path; validate is the structured-result\n      // surface for both shapes, so it parses the arrow and binds null\n      // placeholders for each declared binding so codegen resolves them as\n      // ParamRefs (the values don't affect validation, only their resolution).\n      // Mirror `jsmqlDispatch`'s function-input branch (parse + lower under the\n      // same augment), but bind each declared binding to a null placeholder so\n      // codegen resolves the ParamRefs \u2014 the values don't affect validation.\n      withFunctionInput(fnSource(input), ({ program, bindings }) => {\n        const resolved = new Map<string, unknown>();\n        for (const b of bindings) resolved.set(b.name, null);\n        lowerWithCtx(program, withBindings(EMPTY_CTX, resolved));\n      });\n    } else {\n      jsmql(input);\n    }\n    return { valid: true, errors: [] };\n  } catch (err) {\n    return errorToValidationResult(err);\n  }\n}\n\n// `jsmql` is exposed as a callable with attached properties:\n//   - `jsmql.compile`  \u2014 parameterised, reusable Filter / Pipeline builder\n//   - `jsmql.validate` \u2014 structured-result form of `jsmql()`\n//   - `jsmql.expr`     \u2014 compile a partial / \"unfinished\" aggregation expression\n//                        (the shape that goes inside `$project`, `$addFields`,\n//                        `db.coll.updateOne(filter, update)`, etc.)\n//   - `jsmql.filter`   \u2014 strict-Filter form (throws on Pipeline-shaped input)\n//   - `jsmql.pipeline` \u2014 strict-Pipeline form (throws on bare-expression input)\n//   - `jsmql.update`   \u2014 strict aggregation-pipeline update (whitelists stages).\n//                        Named `update` rather than `updateFilter` to avoid the\n//                        \"filter \u2260 query doc\" confusion at the call site; the\n//                        underlying driver type is still `UpdateFilter<T>`.\n// The strippable-TS rule (see src/CLAUDE.md) forbids `namespace` declarations,\n// so we build the shape with `Object.assign` and an explicit intersection type.\ntype Jsmql = typeof jsmqlDispatch & {\n  compile: typeof compileFunction;\n  validate: typeof validateInput;\n  expr: typeof exprDispatch;\n  filter: typeof filterDispatch;\n  pipeline: typeof pipelineDispatch;\n  update: typeof updateDispatch;\n};\n\nexport const jsmql: Jsmql = Object.assign(jsmqlDispatch, {\n  compile: compileFunction,\n  validate: validateInput,\n  expr: exprDispatch,\n  filter: filterDispatch,\n  pipeline: pipelineDispatch,\n  update: updateDispatch,\n});\n\n// Wrap JSON.stringify with the validation needed to keep the template-tag\n// invocation of `jsmql` a safe boundary. Three failure modes that\n// JSON.stringify quietly hides:\n//   - returns `undefined` for unsupported value types (function/Symbol/the\n//     literal `undefined`); concatenating that into the source produces the\n//     bare text \"undefined\" which the parser then misreads as an identifier.\n//   - silently coerces non-finite numbers to \"null\", losing the user's intent.\n//   - throws TypeError for BigInt values and circular references.\n//\n// A fourth failure mode is fidelity loss: `JSON.stringify(new Date(...))`\n// returns an ISO string (which BSON compares as a string, not a date),\n// `JSON.stringify(/x/)` returns `\"{}\"`, etc. For opaque BSON instances \u2014\n// `Date`, `RegExp`, `Uint8Array`/Buffer, duck-typed `ObjectId` \u2014 the\n// original JS instance is routed through a synthesized `ParamRef` binding\n// so the MQL output carries it verbatim. Works at the top of an\n// interpolation slot *and* arbitrarily deep inside an interpolated\n// object/array \u2014 e.g. `jsmql\\`\u2026 ${{ since: new Date(...) }}\\`` keeps the\n// nested Date as a Date.\n\n// U+E000 is a Unicode Private Use Area code point \u2014 Unicode reserves these\n// for private-use sentinels with no defined meaning, JSON.stringify passes\n// them through unescaped, and they essentially never appear in real user\n// data. Used to wrap an injected binding-name string so we can find-and-\n// replace markers after JSON.stringify produces the source fragment.\nconst OPAQUE_INTERP_MARKER = \"\uE000\";\n\nfunction stringifyInterpolation(value: unknown, slot: number, opaqueBindings: Map<string, unknown>): string {\n  if (!containsOpaqueBsonAnywhere(value)) {\n    // Fast path: pure JSON-shaped value. After validateInterpolatable, JSON.stringify\n    // is guaranteed to produce a string (no `undefined` return, no throw, no silent\n    // NaN\u2192null coercion at top level).\n    validateInterpolatable(value, slot);\n    return JSON.stringify(value)!;\n  }\n  // Slow path: at least one opaque BSON instance lives somewhere in the value.\n  // Substitute each instance with a marker string carrying a unique binding\n  // name, JSON-stringify the rewritten tree (so the surrounding JSON-shaped\n  // parts get the same serialization as the fast path), then replace the\n  // markers in the output with bare identifiers \u2014 which the parser resolves\n  // as `ParamRef`s and the binding map carries through to codegen.\n  const state = { counter: 0, seen: new WeakSet<object>() };\n  const substituted = substituteOpaqueValues(value, slot, opaqueBindings, state);\n  // `substituted` is a pure-JSON tree (the original BSON instances replaced\n  // with marker strings), so the existing validation still applies \u2014 non-\n  // finite top-level numbers, circular references in the surviving structure,\n  // BigInt anywhere, etc. all surface here.\n  validateInterpolatable(substituted, slot);\n  const jsonWithMarkers = JSON.stringify(substituted)!;\n  // Each opaque value appears in the JSON output as `\"<M><name><M>\"` (JSON-\n  // quoted because the substitute was a string). The lookup against the\n  // bindings map disambiguates against the (theoretical) edge case of a user-\n  // supplied string that happens to look like a marker pair around a known\n  // binding name.\n  const markerPattern = new RegExp(`\"${OPAQUE_INTERP_MARKER}([A-Za-z_][A-Za-z0-9_]*)${OPAQUE_INTERP_MARKER}\"`, \"g\");\n  return jsonWithMarkers.replace(markerPattern, (match, name) => (opaqueBindings.has(name) ? name : match));\n}\n\n/**\n * True iff `value` is \u2014 or transitively contains \u2014 an opaque BSON instance.\n * Used to pick between the fast (pure-JSON) and slow (substitute-then-\n * stringify) interpolation paths. Cycle-safe: re-encountering a previously-\n * seen object returns `false`, leaving the cycle to be caught later by\n * JSON.stringify when either path runs.\n */\nfunction containsOpaqueBsonAnywhere(value: unknown, seen?: WeakSet<object>): boolean {\n  if (isOpaqueBsonValue(value)) return true;\n  if (value === null || typeof value !== \"object\") return false;\n  const s = seen ?? new WeakSet<object>();\n  if (s.has(value)) return false;\n  s.add(value);\n  if (Array.isArray(value)) {\n    for (const v of value) if (containsOpaqueBsonAnywhere(v, s)) return true;\n    return false;\n  }\n  for (const v of Object.values(value)) if (containsOpaqueBsonAnywhere(v, s)) return true;\n  return false;\n}\n\n/**\n * Walk `value`, replacing every opaque BSON instance with a marker string\n * carrying a freshly-allocated `__jsmql_interp_<slot>_<n>` binding name.\n * Records the original instance under that name in `bindings`. Plain JSON\n * values pass through unchanged so the surrounding tree retains the exact\n * shape JSON.stringify would have produced for the fast path.\n */\nfunction substituteOpaqueValues(\n  value: unknown,\n  slot: number,\n  bindings: Map<string, unknown>,\n  state: { counter: number; seen: WeakSet<object> },\n): unknown {\n  if (isOpaqueBsonValue(value)) {\n    state.counter += 1;\n    const name = `__jsmql_interp_${slot}_${state.counter}`;\n    bindings.set(name, value);\n    return `${OPAQUE_INTERP_MARKER}${name}${OPAQUE_INTERP_MARKER}`;\n  }\n  if (value === null || typeof value !== \"object\") return value;\n  // Cycle: return the value as-is so JSON.stringify surfaces the standard\n  // \"Converting circular structure to JSON\" error (re-thrown as\n  // `JsmqlInterpolationError` by `validateInterpolatable`).\n  if (state.seen.has(value)) return value;\n  state.seen.add(value);\n  if (Array.isArray(value)) {\n    return value.map((v) => substituteOpaqueValues(v, slot, bindings, state));\n  }\n  const out: Record<string, unknown> = {};\n  for (const [k, v] of Object.entries(value)) {\n    out[k] = substituteOpaqueValues(v, slot, bindings, state);\n  }\n  return out;\n}\n\n/**\n * Validate that `value` is safely embeddable as a JSON literal in the MQL\n * output. Used by both the template-tag interpolation path and the\n * `jsmql.compile()` parameter-binding path. Throws `JsmqlInterpolationError`\n * on any of the three failure modes JSON.stringify mishandles.\n *\n * When called from the template-tag path, `slot` is the 1-based interpolation\n * index and `key` is undefined. When called from `jsmql.compile`, pass `slot=0`\n * and the binding name as `key` \u2014 the resulting error names the binding so the\n * user can find it in their call site.\n */\nfunction validateInterpolatable(value: unknown, slot: number, key?: string): void {\n  const where = key !== undefined ? `parameter '${key}'` : `interpolation slot ${slot}`;\n  if (typeof value === \"number\" && !Number.isFinite(value)) {\n    throw new JsmqlInterpolationError(\n      `jsmql ${where}: ${value} is not a valid JSON value (NaN and \u00B1Infinity have no JSON representation). Replace with null or a finite number.`,\n      slot,\n      key,\n    );\n  }\n  let json: string | undefined;\n  try {\n    json = JSON.stringify(value);\n  } catch (err) {\n    const reason = err instanceof Error ? err.message : String(err);\n    throw new JsmqlInterpolationError(`jsmql ${where} could not be serialised: ${reason}`, slot, key);\n  }\n  if (json === undefined) {\n    const ty = value === undefined ? \"undefined\" : typeof value;\n    throw new JsmqlInterpolationError(\n      `jsmql ${where} has type '${ty}', which has no JSON representation. Pass a string, number, boolean, null, array, or plain object instead.`,\n      slot,\n      key,\n    );\n  }\n}\n\n/**\n * Lower a parsed `Program` to its MQL output. Parametric on a single\n * `lowerExpr` callback that handles the bare-expression branch; the three\n * other branches (Pipeline / UpdateFilter / array-literal Pipeline) are\n * shared between `jsmql()` (Filter) and `jsmql.expr()` (aggregation\n * expression). Less code = better DX inside the codebase too.\n *\n * Dispatch rule (semicolon-driven), using the Node.js MongoDB driver's\n * official terminology \u2014 Filter for `db.coll.find(filter)`, Pipeline for\n * `db.coll.aggregate(pipeline)`:\n *   - `;`-separated statements \u2192 `Pipeline` AST \u2192 Pipeline (stage array).\n *   - UpdateOp chain (`$.a = 1, $.b = 2`) \u2192 update op program (set/unset stages).\n *   - Top-level array literal of stage shapes \u2192 legacy Pipeline form.\n *   - Single expression (no `;`) \u2192 caller-supplied `lowerExpr` decides:\n *     `jsmql()` lowers to a Filter, `jsmql.expr()` to a raw aggregation\n *     expression.\n */\ntype ExprLowering = (ast: Expr, ctx: GenerateCtx) => object;\n\nfunction lowerProgram(ast: Program, ctx: GenerateCtx, lowerExpr: ExprLowering): JsmqlOutput {\n  if (ast.type === \"Pipeline\") return generateImplicitPipeline(ast, ctx);\n  if (ast.type === \"UpdateFilter\") return generateUpdateFilter(ast, ctx);\n  if (isPipelineAst(ast)) return generatePipeline(ast, ctx);\n  return lowerExpr(ast, ctx);\n}\n\n/** Filter-mode lowering: `jsmql()` and `jsmql.compile()` both go through this. */\nfunction lowerWithCtx(ast: Program, ctx: GenerateCtx): JsmqlOutput {\n  // Top-level bare stage call (`$match(...)`, `$project(...)`, \u2026) or single-key\n  // stage-object literal (`{ $match: ... }` \u2014 the shape MongoDB Compass produces\n  // when you copy/paste) is almost always Pipeline intent \u2014 the user wrote a\n  // stage at the top level. Auto-wrap as a one-stage pipeline so\n  // `jsmql(\"$match($.age > 18)\")` produces `[{ $match: { age: { $gt: 18 } } }]`\n  // with no `;` discipline required. Without this, the call would either\n  // throw (the old behaviour) or silently produce `{ $expr: { $match: ... } }`\n  // \u2014 a syntactically valid Filter that MongoDB can't execute.\n  //\n  // Re-uses the normal `generateImplicitPipeline` path so $match's\n  // index-friendly query-translator runs unchanged, and so a stage that has\n  // sub-pipeline fields (`$lookup`, `$unionWith`, `$facet`) recurses through\n  // the same lowering it would inside a `;`-separated pipeline.\n  //\n  // `jsmql.expr()` doesn't get this wrap: a top-level stage call passed to\n  // `jsmql.expr()` is unusual enough (stages aren't aggregation expressions)\n  // that the user almost certainly meant something else, and silently routing\n  // through Pipeline mode there would mask the mistake.\n  if (\n    ast.type !== \"Pipeline\" &&\n    ast.type !== \"UpdateFilter\" &&\n    !isPipelineAst(ast) &&\n    detectStageIntent(ast) !== null\n  ) {\n    const synthetic: Pipeline = { type: \"Pipeline\", stmts: [ast], pos: ast.pos };\n    return generateImplicitPipeline(synthetic, ctx);\n  }\n  // Top-level `$$.<method>(...)` always lowers as a Pipeline statement.\n  // `$$.push(...)` emits `$unionWith` stages; the stream methods (`.filter`,\n  // `.map`, `.slice`, \u2026) lower to their stages (sugar for `$$ = $$.<chain>`),\n  // and an unknown method surfaces a precise registry error. `isSystemStageCall`\n  // extends the same\n  // auto-wrap to the diagnostic source-stage sugar on every ref level \u2014\n  // `$$.indexStats()`, `$$$$.currentOp(...)`, `$$$$.shardedDataDistribution()`\n  // \u2014 which `isCollectionMethodCall` (CollectionRef only) doesn't cover. In\n  // every case: auto-wrap as a one-stage Pipeline so the user doesn't have to\n  // add a trailing `;` to flip into Pipeline mode and doesn't see the generic\n  // ref \"statement-only\" / \"bare reference\" error instead of the targeted one.\n  if (\n    ast.type !== \"Pipeline\" &&\n    ast.type !== \"UpdateFilter\" &&\n    !isPipelineAst(ast) &&\n    (isCollectionMethodCall(ast as Expr) || isSystemStageCall(ast as Expr))\n  ) {\n    const synthetic: Pipeline = { type: \"Pipeline\", stmts: [ast], pos: ast.pos };\n    return generateImplicitPipeline(synthetic, ctx);\n  }\n  // Top-level mutating array method on a writable field-path receiver\n  // (`$.events.push(x)`, `$.events.sort(e => e.t)`, \u2026) without a trailing `;`.\n  // Same reasoning as the `$$.<method>(...)` and stage-call auto-wraps above:\n  // the user has written a statement that only makes sense as a single\n  // Pipeline stage, so route it through Pipeline mode where the mutator\n  // rewrite materialises the assignment. Without this, the bare-expression\n  // path would reach the codegen mutator throw with its \"use the immutable\n  // variant\" hint \u2014 wrong message for a clearly statement-shaped call.\n  // Not done for `jsmql.expr()`: the raw-expression entry point is for\n  // building blocks that get embedded inside an outer stage, where the\n  // mutator throw is the correct error.\n  if (ast.type !== \"Pipeline\" && ast.type !== \"UpdateFilter\" && !isPipelineAst(ast)) {\n    const rewrite = tryRewriteMutatorCall(ast as Expr);\n    if (rewrite.kind === \"rewrite\") {\n      const synthetic: Pipeline = { type: \"Pipeline\", stmts: [ast], pos: ast.pos };\n      return generateImplicitPipeline(synthetic, ctx);\n    }\n  }\n  // An UpdateFilter whose RHS contains lookup syntax can't go through the\n  // bare-doc `generateUpdateFilter` path \u2014 that lowerer doesn't see lookups\n  // and would reach the `DatabaseRef` / `ClusterRef` codegen case and throw\n  // the wrong error. Wrap as a synthetic single-stmt Pipeline so the lookup-\n  // aware pipeline integration in `pipeline.ts` intercepts the assignment-RHS\n  // lookup. This is the path that lights up `jsmql.compile(({ coll }, $) =>\n  // ($.x = $$$[coll].find(...)))` \u2014 a single-stmt arrow body parses as an\n  // UpdateFilter, not a Pipeline, and without this reroute the bound bracket\n  // index would never reach the lookup translator.\n  if (ast.type === \"UpdateFilter\" && containsLookupCall(ast, ctx)) {\n    const synthetic: Pipeline = { type: \"Pipeline\", stmts: [ast], pos: ast.pos };\n    return generateImplicitPipeline(synthetic, ctx);\n  }\n  // An UpdateFilter whose LHS is the `$out` sugar shape (`$$$.<coll> = \u2026`,\n  // `$$$$.<db>.<coll> = \u2026`) follows the same reroute logic as the lookup\n  // case: the bare-doc `generateUpdateFilter` path doesn't know about\n  // `$out` lowering and would surface the generic `DatabaseRef` / `ClusterRef`\n  // bare-reference error. Wrap as a one-stmt Pipeline so the pipeline\n  // integration in `pipeline.ts` recognises and lowers the `$out`.\n  if (ast.type === \"UpdateFilter\" && containsOutAssign(ast)) {\n    const synthetic: Pipeline = { type: \"Pipeline\", stmts: [ast], pos: ast.pos };\n    return generateImplicitPipeline(synthetic, ctx);\n  }\n  // Lookup syntax in the bare-expression branch (no `;`, no stage call, no\n  // update op): would produce a stray `DatabaseRef` / `ClusterRef` error.\n  // Catch it here so the message points at the right shape \u2014 add a `;` (or\n  // any update op / let / stage call) to flip into Pipeline mode.\n  if (\n    ast.type !== \"Pipeline\" &&\n    ast.type !== \"UpdateFilter\" &&\n    !isPipelineAst(ast) &&\n    detectStageIntent(ast) === null &&\n    containsLookupCall(ast, ctx)\n  ) {\n    throw new CodegenError(\n      \"Lookup syntax ('$$$.<coll>.find/filter(...)') requires Pipeline mode. \" +\n        \"Assign the lookup to a field (`$.x = $$$.coll.find(...)`) or wrap in a let / pipeline statement, \" +\n        \"and ensure the source has at least one `;` so jsmql routes through Pipeline lowering.\",\n      ast.pos,\n    );\n  }\n  const result = lowerProgram(ast, ctx, generateFilter);\n  // Update-filter inputs that compile to a single stage (`{ $set: { \u2026RHS\u2026 } }`\n  // or `{ $unset: \"x\" }`) get wrapped into a one-element pipeline at the\n  // `jsmql()` entry point. Rationale: the second argument to\n  // `db.coll.updateOne(filter, update)` is treated by MongoDB as an\n  // **aggregation pipeline** only when it's an array \u2014 the bare-document form\n  // treats every value as a literal, so a computed RHS like `$.name.toUpperCase()`\n  // would silently land in the document as the object `{ $toUpper: \"$name\" }`\n  // instead of evaluating. Always returning an array from `jsmql()` makes the\n  // call site `db.coll.updateOne({\u2026}, jsmql(\u2026))` work safely regardless of\n  // whether the RHS happens to be a literal or an expression. Callers who\n  // explicitly want the bare update-document shape (e.g. for embedding inside\n  // a hand-written pipeline stage body) use `jsmql.expr()` \u2014 `lowerExprWithCtx`\n  // intentionally does not wrap.\n  if (ast.type === \"UpdateFilter\" && !Array.isArray(result)) {\n    return [result];\n  }\n  return result;\n}\n\n/** Expression-mode lowering: `jsmql.expr()` goes through this. */\nfunction lowerExprWithCtx(ast: Program, ctx: GenerateCtx): JsmqlOutput {\n  rejectLookupOutsidePipeline(ast, \"jsmql.expr\", ctx);\n  rejectUnionPushOutsidePipeline(ast, \"jsmql.expr\");\n  rejectOutOutsidePipeline(ast, \"jsmql.expr\");\n  // No array-wrap for update-filter output (see `lowerWithCtx` comment): the\n  // caller asked for a raw building block, the bare `{ $set: \u2026 }` shape is\n  // exactly what fits inside a hand-written `$set` / `$addFields` stage or\n  // gets passed to a doc-form update operation that wants literal semantics.\n  return lowerProgram(ast, ctx, (e, c) => generateWithCtx(e, c) as object);\n}\n\n/**\n * Strict Filter-mode lowering: `jsmql.filter()` goes through this.\n *\n * Every Pipeline-shaped input that `jsmql()` would auto-route to Pipeline\n * mode throws here instead, with a message naming the shape that was found\n * and pointing at the right alternative entry point. The accepted branch is\n * exactly the bare-expression path of `lowerWithCtx`, lowered through\n * `generateFilter` (same engine, same indexable-conjunct translation, same\n * `$expr` fallback for the untranslatable residual).\n */\nfunction lowerFilterStrict(ast: Program, ctx: GenerateCtx): JsmqlOutput {\n  rejectLookupOutsidePipeline(ast, \"jsmql.filter\", ctx);\n  rejectUnionPushOutsidePipeline(ast, \"jsmql.filter\");\n  rejectOutOutsidePipeline(ast, \"jsmql.filter\");\n  if (ast.type === \"Pipeline\") {\n    throw new CodegenError(\n      \"jsmql.filter() expects a Filter (the document `db.coll.find(filter)` takes), but received a `;`-separated Pipeline. \" +\n        \"Drop the `;` to compose a Filter, or call jsmql.pipeline() / jsmql() for Pipeline output.\",\n      ast.pos,\n    );\n  }\n  if (ast.type === \"UpdateFilter\") {\n    throw new CodegenError(\n      \"jsmql.filter() expects a Filter, but received an update-op chain (e.g. `$.x = \u2026`, `delete $.x`). \" +\n        \"Update-op chains compile to `$set` / `$unset` stages \u2014 call jsmql.update() or jsmql() for the Pipeline form.\",\n      ast.pos,\n    );\n  }\n  if (isPipelineAst(ast)) {\n    throw new CodegenError(\n      \"jsmql.filter() expects a Filter, but received a Pipeline array (`[{ $stage: ... }, ...]`). \" +\n        \"Call jsmql.pipeline() or jsmql() for Pipeline output.\",\n      ast.pos,\n    );\n  }\n  const stageName = detectStageIntent(ast);\n  if (stageName !== null) {\n    const hint =\n      stageName === \"$match\"\n        ? \" \u2014 or, if you wanted a Filter, drop the `$match(...)` wrapper and pass the predicate directly to jsmql.filter().\"\n        : \".\";\n    throw new CodegenError(\n      `jsmql.filter() expects a Filter, but received a top-level '${stageName}' stage call. ` +\n        `Call jsmql.pipeline() or jsmql() for Pipeline output${hint}`,\n      ast.pos,\n    );\n  }\n  return generateFilter(ast, ctx);\n}\n\n/** Strict Pipeline-mode lowering: `jsmql.pipeline()` goes through this. */\nfunction lowerPipelineStrict(ast: Program, ctx: GenerateCtx): JsmqlOutput {\n  return lowerToPipelineStages(ast, ctx, \"jsmql.pipeline\");\n}\n\n/**\n * Aggregation-pipeline update lowering: `jsmql.update()` goes through this.\n * Reuses `lowerToPipelineStages` to share the bare-expression rejection with\n * `jsmql.pipeline()`, then enforces the update-pipeline stage whitelist so a\n * stage MongoDB would refuse at runtime (`$match`, `$sort`, `$group`, \u2026)\n * gets caught at compile time with the offending name in the message.\n *\n * (The internal name keeps `Update` rather than `UpdateFilter` to match the\n * public API. The AST node type is still `UpdateFilter` \u2014 that's a parser\n * concept, not an API concept, and matches the MongoDB driver's typings.)\n */\nfunction lowerUpdateStrict(ast: Program, ctx: GenerateCtx): JsmqlOutput {\n  // MongoDB's update-pipeline form whitelists only $addFields/$set, $project/$unset,\n  // $replaceRoot/$replaceWith \u2014 $lookup isn't in that list (it's documented as\n  // disallowed on every update method's reference page). Catching the lookup\n  // syntax pre-codegen gives a message that names the right entry point instead\n  // of the generic \"rejected '$lookup'\" produced by the downstream whitelist.\n  if (containsLookupCall(ast, ctx)) {\n    throw new CodegenError(\n      \"jsmql.update() does not allow lookup syntax ('$$$.<coll>.find/filter(...)'): MongoDB's aggregation-pipeline update form only accepts \" +\n        Array.from(UPDATE_PIPELINE_STAGES).sort().join(\", \") +\n        \". Run the lookup in a regular aggregation pipeline (jsmql.pipeline()) and apply updates separately.\",\n      ast.pos,\n    );\n  }\n  if (containsUnionPush(ast)) {\n    throw new CodegenError(\n      \"jsmql.update() does not allow '$$.push(...)' (collection union): MongoDB's aggregation-pipeline update form only accepts \" +\n        Array.from(UPDATE_PIPELINE_STAGES).sort().join(\", \") +\n        \". Run the union in a regular aggregation pipeline (jsmql.pipeline()) \u2014 '$unionWith' isn't allowed inside an update.\",\n      ast.pos,\n    );\n  }\n  const stages = lowerToPipelineStages(ast, ctx, \"jsmql.update\");\n  for (let i = 0; i < stages.length; i++) {\n    const stageName = Object.keys(stages[i] as Record<string, unknown>)[0];\n    if (!UPDATE_PIPELINE_STAGES.has(stageName)) {\n      const allowed = Array.from(UPDATE_PIPELINE_STAGES).sort().join(\", \");\n      throw new CodegenError(\n        `jsmql.update() rejected '${stageName}' (stage ${i}): MongoDB's aggregation-pipeline update form only accepts ${allowed}. ` +\n          `Use jsmql.pipeline() if you need other stages.`,\n        ast.pos,\n      );\n    }\n  }\n  return stages;\n}\n\n/**\n * Lookup syntax (`$$$.<coll>.find/filter(...)`) requires Pipeline mode \u2014\n * the lowering emits `$lookup` (+ follow-up) stages. Filter mode /\n * `jsmql.expr` would just see a stray `DatabaseRef` and surface the\n * generic bare-reference error; this pre-gate gives a precise message\n * naming the right entry point instead.\n */\nfunction rejectLookupOutsidePipeline(ast: Program, apiName: string, ctx: GenerateCtx): void {\n  if (containsLookupCall(ast, ctx)) {\n    throw new CodegenError(\n      `${apiName}() does not allow lookup syntax ('$$$.<coll>.find/filter(...)') \u2014 joins are Pipeline-only. ` +\n        \"Use jsmql() (in Pipeline mode) or jsmql.pipeline() for cross-collection queries.\",\n      ast.pos,\n    );\n  }\n}\n\n/**\n * Union-push syntax (`$$.push(...)`) is statement-only and lowers to\n * `$unionWith` stages \u2014 Pipeline-mode-only. Filter mode / `jsmql.expr` /\n * `jsmql.update` reject it at a pre-codegen pass so the error names the\n * right entry point and the right shape (`$unionWith` isn't even in the\n * update-pipeline whitelist).\n */\nfunction rejectUnionPushOutsidePipeline(ast: Program, apiName: string): void {\n  if (containsUnionPush(ast)) {\n    throw new CodegenError(\n      `${apiName}() does not allow '$$.push(...)' \u2014 collection unions are Pipeline-only. ` +\n        \"Use jsmql() (in Pipeline mode) or jsmql.pipeline() to compose '$unionWith' stages.\",\n      ast.pos,\n    );\n  }\n}\n\n/**\n * `$out` sugar (`$$$.<coll> = \u2026`, `$$$$.<db>.<coll> = \u2026`) is Pipeline-only \u2014\n * the assignment lowers to a `$out` stage. Filter / `jsmql.expr` would see\n * a stray `DatabaseRef` / `ClusterRef` LHS and surface the generic bare-\n * reference error; this pre-gate gives a precise \"use Pipeline mode\" message\n * naming the right entry point.\n */\nfunction rejectOutOutsidePipeline(ast: Program, apiName: string): void {\n  if (containsOutAssign(ast)) {\n    throw new CodegenError(\n      `${apiName}() does not allow '$out' sugar ('$$$.<coll> = \u2026' / '$$$$.<db>.<coll> = \u2026') \u2014 '$out' is a pipeline stage. ` +\n        \"Use jsmql() (in Pipeline mode \u2014 add ';' or wrap in a stage array) or jsmql.pipeline() to compose '$out' stages.\",\n      ast.pos,\n    );\n  }\n}\n\n/**\n * Shared body of `jsmql.pipeline()` and `jsmql.update()`: route every\n * Pipeline-shape branch to its existing lowerer and throw an actionable error\n * for a bare expression (the only input shape `jsmql()` would have routed to\n * Filter mode). `apiName` is interpolated into the error so the message\n * names the actual entry point the user called.\n */\nfunction lowerToPipelineStages(ast: Program, ctx: GenerateCtx, apiName: string): object[] {\n  if (ast.type === \"Pipeline\") return generateImplicitPipeline(ast, ctx) as object[];\n  if (ast.type === \"UpdateFilter\") {\n    // `$out` sugar (`$$$.<coll> = \u2026`) inside an UpdateFilter must go through\n    // pipeline lowering \u2014 `generateUpdateFilter` doesn't know about it. Reroute\n    // the same way `lowerWithCtx` does for the implicit `jsmql()` entry.\n    if (containsOutAssign(ast)) {\n      const synthetic: Pipeline = { type: \"Pipeline\", stmts: [ast], pos: ast.pos };\n      return generateImplicitPipeline(synthetic, ctx) as object[];\n    }\n    const result = generateUpdateFilter(ast, ctx);\n    return Array.isArray(result) ? result : [result];\n  }\n  if (isPipelineAst(ast)) return generatePipeline(ast, ctx) as object[];\n  // A bare stage call (`$match(...)`) or a diagnostic source-stage sugar\n  // (`$$.indexStats()`, `$$$$.currentOp(...)`, `$$$$.shardedDataDistribution()`)\n  // is a one-stage Pipeline \u2014 wrap it so the user needn't add a trailing `;`.\n  if (detectStageIntent(ast) !== null || isSystemStageCall(ast as Expr)) {\n    const synthetic: Pipeline = { type: \"Pipeline\", stmts: [ast], pos: ast.pos };\n    return generateImplicitPipeline(synthetic, ctx) as object[];\n  }\n  throw new CodegenError(\n    `${apiName}() expects a Pipeline (one or more aggregation stages \u2014 \\`;\\`-separated, a top-level stage call, or a stage-array literal), ` +\n      `but received a bare expression that would lower to a Filter document. ` +\n      `Call jsmql.filter() or jsmql() for Filter output, or wrap the predicate as \\`$match(...)\\` to make it a Pipeline.`,\n    ast.pos,\n  );\n}\n\n/**\n * The stages MongoDB allows inside an aggregation-pipeline update (the array\n * form of the second argument to `db.coll.updateOne` / `updateMany`). Any\n * stage outside this set is rejected by the server at runtime; `jsmql.update()`\n * catches it at compile time. See\n * https://www.mongodb.com/docs/manual/reference/method/db.collection.updateOne/#update-with-aggregation-pipeline.\n */\nconst UPDATE_PIPELINE_STAGES = new Set<string>([\n  \"$addFields\",\n  \"$project\",\n  \"$replaceRoot\",\n  \"$replaceWith\",\n  \"$set\",\n  \"$unset\",\n]);\n\n/**\n * Lower a single expression AST to a MongoDB **Filter** (the document passed\n * as the first argument to `db.coll.find(filter)`).\n *\n * Reuses the same translator that `$match` uses inside a Pipeline\n * (`translateMatchBody`): translatable conjuncts emit indexable `{ field: ... }`\n * pairs; an untranslatable residual is wrapped in `$expr`, which is a legal\n * top-level Filter operator. So both predicates (`$.age > 18` \u2192\n * `{ age: { $gt: 18 } }`) and non-predicate expressions\n * (`$abs(42)` \u2192 `{ $expr: { $abs: 42 } }`) produce a valid Filter document.\n *\n * Stage-intent shapes (`$match(...)`, `{ $match: ... }`, \u2026) never reach this\n * function \u2014 they are caught in `lowerWithCtx` and routed through\n * `generateImplicitPipeline` so the user sees an auto-wrapped one-stage\n * Pipeline instead of a useless `{ $expr: { $match: ... } }` Filter.\n */\nfunction generateFilter(ast: Expr, ctx: GenerateCtx): object {\n  const t = translateMatchBody(ast, { bindings: ctx.bindings });\n  // `?? {}`: a vacuous predicate yields the empty (match-everything) Filter.\n  return mergeTranslatedQuery(t, ctx) ?? {};\n}\n\n/**\n * Recognise the two shapes a Pipeline stage takes at the top level: a stage\n * **call** (`$match(...)`, `$project(...)`) and a stage **object** literal\n * (`{ $match: ... }`, the form MongoDB Compass copy-paste produces). Returns\n * the stage name when matched, null otherwise. Used by `generateFilter` to\n * catch the \"forgot the `;`\" case before the silent `$expr` wrap fires.\n */\n/**\n * Top-level `$$.<method>(...)` is always a Pipeline statement: `.push(...)`\n * lowers to `$unionWith`, the stream methods (`.filter`, `.map`, `.slice`, \u2026)\n * lower to their stages as a bare-statement chain (sugar for `$$ = $$.<chain>`),\n * and an unknown method surfaces an actionable registry error. Detecting any\n * method call on a `CollectionRef` receiver here lets the auto-wrap route the\n * input through Pipeline mode so the user doesn't have to add a trailing `;`,\n * and sees the targeted stream error instead of the generic CollectionRef\n * \"statement-only\" codegen throw.\n */\nfunction isCollectionMethodCall(ast: Expr): boolean {\n  return ast.type === \"MethodCall\" && ast.object.type === \"CollectionRef\";\n}\n\nfunction detectStageIntent(ast: Expr): string | null {\n  if (ast.type === \"OperatorCall\" && lookupStage(ast.name) !== undefined) {\n    return ast.name;\n  }\n  if (ast.type === \"ObjectLiteral\" && ast.entries.length === 1) {\n    const entry = ast.entries[0];\n    if (entry.type === \"KeyValueEntry\" && entry.key.kind === \"static\" && lookupStage(entry.key.name) !== undefined) {\n      return entry.key.name;\n    }\n  }\n  return null;\n}\n\n/**\n * Map a thrown error to the structured `ValidationResult` shape. Kept as a\n * standalone helper so the per-error-class branch table lives in one place,\n * which keeps the contract on `jsmql.validate()` stable as new error types\n * are introduced over time.\n */\nfunction errorToValidationResult(err: unknown): ValidationResult {\n  if (err instanceof ParseError || err instanceof LexError) {\n    return { valid: false, errors: [{ message: err.message, pos: err.pos, code: \"SYNTAX_ERROR\" }] };\n  }\n  if (err instanceof CodegenError) {\n    return { valid: false, errors: [{ message: err.message, pos: err.pos, code: \"CODEGEN_ERROR\" }] };\n  }\n  if (err instanceof FunctionInputError) {\n    return { valid: false, errors: [{ message: err.message, pos: err.pos, code: \"SYNTAX_ERROR\" }] };\n  }\n  // JsmqlInterpolationError carries `.slot` (1-based interpolation index) and\n  // optionally `.key` (param name) instead of a source offset \u2014 there is no\n  // single byte offset in the template-tag form because the template's text\n  // lives across the `strings`/`values` arrays. Callers needing to locate the\n  // failing interpolation should read `.slot` / `.key` on the error directly.\n  if (err instanceof JsmqlInterpolationError) {\n    return { valid: false, errors: [{ message: err.message, pos: 0, code: \"SYNTAX_ERROR\" }] };\n  }\n  // RangeError is what V8 throws on stack overflow \u2014 caused by input shape,\n  // so it belongs in the SYNTAX_ERROR bucket. Should be unreachable in\n  // practice now that the parser/codegen depth limits trip first, but keep\n  // the catch as a belt-and-braces safeguard. TypeError lands here too: it\n  // comes from `jsmql()`'s top-level guard rejecting a wrong-shape input,\n  // which is a \"your input is wrong\" failure from the caller's perspective.\n  if (err instanceof RangeError || err instanceof TypeError) {\n    return { valid: false, errors: [{ message: err.message, pos: 0, code: \"SYNTAX_ERROR\" }] };\n  }\n  // validate() promises never to throw \u2014 anything else gets wrapped as a\n  // generic CODEGEN_ERROR so the caller can rely on the structured-result\n  // contract. The original message is preserved for debugging.\n  const message = err instanceof Error ? err.message : String(err);\n  return { valid: false, errors: [{ message: `internal error: ${message}`, pos: 0, code: \"CODEGEN_ERROR\" }] };\n}\n\nfunction augmentForFunctionInput(err: unknown): unknown {\n  if (err instanceof UnknownIdentifierError) {\n    err.message =\n      `${err.message}\\n` +\n      `If '${err.identifier}' is a binding you want to supply at call time, use ` +\n      `jsmql.compile(fn)({ ${err.identifier}: \u2026 }) and add it to the params destructure: ` +\n      `({ ${err.identifier} }, $) => \u2026\\n` +\n      `If '${err.identifier}' is a value from outer scope, use the jsmql\\`\\` template tag: ` +\n      `jsmql\\`\u2026 \\${${err.identifier}} \u2026\\``;\n  }\n  return err;\n}\n", "// Type-strippable replacement for the original `const enum TokenType`. The\n// `as const` object preserves the `TokenType.LParen` call-site idiom (no\n// churn at the 196 use sites), and the derived union gives us the same\n// type-checking guarantees. Trades the const-enum's compile-time inlining\n// for a small runtime object \u2014 negligible for a lexer.\nexport const TokenType = {\n  // Punctuation\n  LParen: \"LParen\", // (\n  RParen: \"RParen\", // )\n  LBracket: \"LBracket\", // [\n  RBracket: \"RBracket\", // ]\n  LBrace: \"LBrace\", // {\n  RBrace: \"RBrace\", // }\n  Comma: \"Comma\", // ,\n  Semi: \"Semi\", // ;\n  Colon: \"Colon\", // :\n  Dot: \"Dot\", // .\n  QuestDot: \"QuestDot\", // ?.  (optional chaining)\n  DollarDot: \"DollarDot\", // $.\n  Dollar: \"Dollar\", // $ (standalone, before IDENT for operator)\n  DoubleDollar: \"DoubleDollar\", // $$  (current-collection reference, postfix .name or [expr])\n  TripleDollar: \"TripleDollar\", // $$$  (current-database reference)\n  QuadDollar: \"QuadDollar\", // $$$$  (current-cluster reference)\n  Spread: \"Spread\", // ...\n\n  // Arithmetic operators\n  Plus: \"Plus\", // +\n  Minus: \"Minus\", // -\n  Star: \"Star\", // *\n  StarStar: \"StarStar\", // **\n  Slash: \"Slash\", // /\n  Percent: \"Percent\", // %\n\n  // Increment / decrement (update op statements; not value expressions)\n  PlusPlus: \"PlusPlus\", // ++\n  MinusMinus: \"MinusMinus\", // --\n\n  // Assignment operators\n  Eq: \"Eq\", // =\n  PlusEq: \"PlusEq\", // +=\n  MinusEq: \"MinusEq\", // -=\n  StarEq: \"StarEq\", // *=\n  SlashEq: \"SlashEq\", // /=\n\n  // Comparison operators\n  EqEq: \"EqEq\", // ==\n  EqEqEq: \"EqEqEq\", // ===\n  BangEq: \"BangEq\", // !=\n  BangEqEq: \"BangEqEq\", // !==\n  Gt: \"Gt\", // >\n  GtEq: \"GtEq\", // >=\n  Lt: \"Lt\", // <\n  LtEq: \"LtEq\", // <=\n\n  // Logical operators\n  AmpAmp: \"AmpAmp\", // &&\n  PipePipe: \"PipePipe\", // ||\n  Bang: \"Bang\", // !\n\n  // Bitwise operators\n  Amp: \"Amp\", // &\n  Pipe: \"Pipe\", // |\n  Caret: \"Caret\", // ^\n  Tilde: \"Tilde\", // ~\n\n  // Misc operators\n  QuestQuest: \"QuestQuest\", // ??\n  Quest: \"Quest\", // ?\n  Arrow: \"Arrow\", // =>\n\n  // Literals\n  Number: \"Number\",\n  BigInt: \"BigInt\", // 123n\n  String: \"String\",\n  True: \"True\",\n  False: \"False\",\n  Null: \"Null\",\n  Undefined: \"Undefined\",\n  RegexLiteral: \"RegexLiteral\", // /pattern/flags\n\n  // Template literals\n  TemplateStart: \"TemplateStart\", // opening `\n  TemplateChars: \"TemplateChars\", // literal chunk between ` and ${ (or ` and `)\n  TemplateExprStart: \"TemplateExprStart\", // ${\n  TemplateEnd: \"TemplateEnd\", // closing `\n\n  // Keywords\n  In: \"In\", // in\n  New: \"New\", // new\n  Typeof: \"Typeof\", // typeof\n  Delete: \"Delete\", // delete\n  Let: \"Let\", // let\n\n  // Identifier\n  Ident: \"Ident\",\n\n  EOF: \"EOF\",\n} as const;\nexport type TokenType = (typeof TokenType)[keyof typeof TokenType];\n\n/**\n * Human-friendly display string for each token type, used in lexer/parser error\n * messages so users see `'('` instead of the internal `LParen` enum name. For\n * punctuation we quote the literal character(s); for value-bearing tokens\n * (identifiers, numbers, strings, \u2026) we use a descriptive word so the message\n * still reads naturally when paired with `got 'foo'`. Keep in sync with the\n * `TokenType` declaration above.\n */\nexport const TOKEN_DISPLAY: Record<TokenType, string> = {\n  LParen: \"'('\",\n  RParen: \"')'\",\n  LBracket: \"'['\",\n  RBracket: \"']'\",\n  LBrace: \"'{'\",\n  RBrace: \"'}'\",\n  Comma: \"','\",\n  Semi: \"';'\",\n  Colon: \"':'\",\n  Dot: \"'.'\",\n  QuestDot: \"'?.'\",\n  DollarDot: \"'$.'\",\n  Dollar: \"'$'\",\n  DoubleDollar: \"'$$'\",\n  TripleDollar: \"'$$$'\",\n  QuadDollar: \"'$$$$'\",\n  Spread: \"'...'\",\n  Plus: \"'+'\",\n  Minus: \"'-'\",\n  Star: \"'*'\",\n  StarStar: \"'**'\",\n  Slash: \"'/'\",\n  Percent: \"'%'\",\n  PlusPlus: \"'++'\",\n  MinusMinus: \"'--'\",\n  Eq: \"'='\",\n  PlusEq: \"'+='\",\n  MinusEq: \"'-='\",\n  StarEq: \"'*='\",\n  SlashEq: \"'/='\",\n  EqEq: \"'=='\",\n  EqEqEq: \"'==='\",\n  BangEq: \"'!='\",\n  BangEqEq: \"'!=='\",\n  Gt: \"'>'\",\n  GtEq: \"'>='\",\n  Lt: \"'<'\",\n  LtEq: \"'<='\",\n  AmpAmp: \"'&&'\",\n  PipePipe: \"'||'\",\n  Bang: \"'!'\",\n  Amp: \"'&'\",\n  Pipe: \"'|'\",\n  Caret: \"'^'\",\n  Tilde: \"'~'\",\n  QuestQuest: \"'??'\",\n  Quest: \"'?'\",\n  Arrow: \"'=>'\",\n  Number: \"a number\",\n  BigInt: \"a BigInt literal\",\n  String: \"a string\",\n  True: \"'true'\",\n  False: \"'false'\",\n  Null: \"'null'\",\n  Undefined: \"'undefined'\",\n  RegexLiteral: \"a regex literal\",\n  TemplateStart: \"a template literal\",\n  TemplateChars: \"template-literal text\",\n  TemplateExprStart: \"'${'\",\n  TemplateEnd: \"'`'\",\n  In: \"'in'\",\n  New: \"'new'\",\n  Typeof: \"'typeof'\",\n  Delete: \"'delete'\",\n  Let: \"'let'\",\n  Ident: \"an identifier\",\n  EOF: \"end of input\",\n};\n\n/**\n * Format a token for the \"but got X\" half of an error message. For value-bearing\n * tokens (identifiers, numbers, strings) the actual lexeme is more useful than\n * the category name, so we render it as e.g. `an identifier 'foo'` or\n * `a number '42'`. For punctuation the display already *is* the lexeme, so the\n * `('${value}')` suffix would be redundant.\n */\nexport function formatActualToken(t: Token): string {\n  const display = TOKEN_DISPLAY[t.type];\n  if (\n    t.type === TokenType.Ident ||\n    t.type === TokenType.Number ||\n    t.type === TokenType.BigInt ||\n    t.type === TokenType.String ||\n    t.type === TokenType.RegexLiteral\n  ) {\n    return `${display} '${t.value}'`;\n  }\n  return display;\n}\n\nexport type Token = {\n  type: TokenType;\n  value: string;\n  pos: number;\n  flags?: string; // only set for RegexLiteral tokens\n};\n\nexport class LexError extends Error {\n  readonly pos: number;\n  constructor(message: string, pos: number) {\n    super(message);\n    this.name = \"LexError\";\n    this.pos = pos;\n  }\n}\n\n// Token types that end a \"value\" \u2014 after these, `/` is a divide operator.\n// After anything else, `/` starts a regex literal.\nconst VALUE_ENDING_TYPES = new Set<TokenType>([\n  TokenType.Number,\n  TokenType.BigInt,\n  TokenType.String,\n  TokenType.True,\n  TokenType.False,\n  TokenType.Null,\n  TokenType.Undefined,\n  TokenType.Ident,\n  TokenType.RParen,\n  TokenType.RBracket,\n  TokenType.TemplateEnd,\n]);\n\nexport class Lexer {\n  private pos = 0;\n  private readonly tokens: Token[] = [];\n  private tokenIdx = 0;\n  private lastTokenType: TokenType | null = null;\n\n  // Brace depth tracking for template literal expression interpolation.\n  // Each entry on templateBraceDepths is the brace depth at which a `${` was opened \u2014\n  // when a `}` would bring us back to that depth, it closes the template expression\n  // instead of being a normal RBrace.\n  private braceDepth = 0;\n  private templateBraceDepths: number[] = [];\n\n  private readonly src: string;\n  constructor(src: string) {\n    this.src = src;\n    this.tokenize();\n  }\n\n  peek(): Token {\n    return this.tokens[this.tokenIdx] ?? { type: TokenType.EOF, value: \"\", pos: this.src.length };\n  }\n\n  next(): Token {\n    const t = this.peek();\n    this.tokenIdx++;\n    return t;\n  }\n\n  lookahead(offset: number): Token {\n    return this.tokens[this.tokenIdx + offset] ?? { type: TokenType.EOF, value: \"\", pos: this.src.length };\n  }\n\n  expect(type: TokenType): Token {\n    const t = this.next();\n    if (t.type !== type) {\n      throw new LexError(`Expected ${TOKEN_DISPLAY[type]} but got ${formatActualToken(t)} at position ${t.pos}`, t.pos);\n    }\n    return t;\n  }\n\n  private pushToken(tok: Token): void {\n    this.tokens.push(tok);\n    this.lastTokenType = tok.type;\n  }\n\n  private tokenize(): void {\n    const src = this.src;\n    const len = src.length;\n\n    while (this.pos < len) {\n      this.skipTrivia();\n      if (this.pos >= len) break;\n\n      const start = this.pos;\n      const ch = src[this.pos];\n      const ch2 = src[this.pos + 1] ?? \"\";\n      const ch3 = src[this.pos + 2] ?? \"\";\n\n      // Single-char punctuation\n      if (ch === \"(\") {\n        this.emit(TokenType.LParen, \"(\", start, 1);\n        continue;\n      }\n      if (ch === \")\") {\n        this.emit(TokenType.RParen, \")\", start, 1);\n        continue;\n      }\n      if (ch === \"[\") {\n        this.emit(TokenType.LBracket, \"[\", start, 1);\n        continue;\n      }\n      if (ch === \"]\") {\n        this.emit(TokenType.RBracket, \"]\", start, 1);\n        continue;\n      }\n      if (ch === \"{\") {\n        this.emit(TokenType.LBrace, \"{\", start, 1);\n        this.braceDepth++;\n        continue;\n      }\n      if (ch === \"}\") {\n        // If this } closes a template expression, switch back to template-chunk reading\n        if (\n          this.templateBraceDepths.length > 0 &&\n          this.templateBraceDepths[this.templateBraceDepths.length - 1] === this.braceDepth\n        ) {\n          this.templateBraceDepths.pop();\n          this.pos++; // consume }\n          this.readTemplateChunk(start);\n          continue;\n        }\n        this.emit(TokenType.RBrace, \"}\", start, 1);\n        this.braceDepth--;\n        continue;\n      }\n      if (ch === \",\") {\n        this.emit(TokenType.Comma, \",\", start, 1);\n        continue;\n      }\n      if (ch === \";\") {\n        this.emit(TokenType.Semi, \";\", start, 1);\n        continue;\n      }\n      if (ch === \":\") {\n        this.emit(TokenType.Colon, \":\", start, 1);\n        continue;\n      }\n\n      // Spread ... (must come before single dot)\n      if (ch === \".\" && ch2 === \".\" && ch3 === \".\") {\n        this.emit(TokenType.Spread, \"...\", start, 3);\n        continue;\n      }\n      if (ch === \".\") {\n        this.emit(TokenType.Dot, \".\", start, 1);\n        continue;\n      }\n\n      // $ family \u2014 longest-match over consecutive '$' chars:\n      //   $    \u2192 Dollar         (operator prefix, e.g. $add)\n      //   $.   \u2192 DollarDot       (current-document field ref, $.x)\n      //   $$   \u2192 DoubleDollar    (current-collection ref, $$.x / $$[x])\n      //   $$$  \u2192 TripleDollar    (current-database ref, $$$.x / $$$[x])\n      //   $$$$ \u2192 QuadDollar      (current-cluster ref, $$$$.x / $$$$[x])\n      //   $$$$$+ \u2192 LexError (no levels deeper than cluster are defined)\n      if (ch === \"$\") {\n        let dollarCount = 1;\n        while (src[start + dollarCount] === \"$\") dollarCount++;\n        if (dollarCount === 1) {\n          if (ch2 === \".\") {\n            this.emit(TokenType.DollarDot, \"$.\", start, 2);\n          } else {\n            this.emit(TokenType.Dollar, \"$\", start, 1);\n          }\n          continue;\n        }\n        if (dollarCount === 2) {\n          this.emit(TokenType.DoubleDollar, \"$$\", start, 2);\n          continue;\n        }\n        if (dollarCount === 3) {\n          this.emit(TokenType.TripleDollar, \"$$$\", start, 3);\n          continue;\n        }\n        if (dollarCount === 4) {\n          this.emit(TokenType.QuadDollar, \"$$$$\", start, 4);\n          continue;\n        }\n        throw new LexError(\n          `Up to 4 levels of context reference are supported ('$.', '$$', '$$$', '$$$$') at position ${start}`,\n          start,\n        );\n      }\n\n      // ** before *= before *\n      if (ch === \"*\" && ch2 === \"*\") {\n        this.emit(TokenType.StarStar, \"**\", start, 2);\n        continue;\n      }\n      if (ch === \"*\" && ch2 === \"=\") {\n        this.emit(TokenType.StarEq, \"*=\", start, 2);\n        continue;\n      }\n      if (ch === \"*\") {\n        this.emit(TokenType.Star, \"*\", start, 1);\n        continue;\n      }\n\n      // === before == before => before bare = (assignment)\n      if (ch === \"=\") {\n        if (ch2 === \"=\" && ch3 === \"=\") {\n          this.emit(TokenType.EqEqEq, \"===\", start, 3);\n          continue;\n        }\n        if (ch2 === \"=\") {\n          this.emit(TokenType.EqEq, \"==\", start, 2);\n          continue;\n        }\n        if (ch2 === \">\") {\n          this.emit(TokenType.Arrow, \"=>\", start, 2);\n          continue;\n        }\n        this.emit(TokenType.Eq, \"=\", start, 1);\n        continue;\n      }\n\n      // !== before != before !\n      if (ch === \"!\") {\n        if (ch2 === \"=\" && ch3 === \"=\") {\n          this.emit(TokenType.BangEqEq, \"!==\", start, 3);\n          continue;\n        }\n        if (ch2 === \"=\") {\n          this.emit(TokenType.BangEq, \"!=\", start, 2);\n          continue;\n        }\n        this.emit(TokenType.Bang, \"!\", start, 1);\n        continue;\n      }\n\n      // >= before >\n      if (ch === \">\") {\n        if (ch2 === \"=\") {\n          this.emit(TokenType.GtEq, \">=\", start, 2);\n          continue;\n        }\n        this.emit(TokenType.Gt, \">\", start, 1);\n        continue;\n      }\n\n      // <= before <\n      if (ch === \"<\") {\n        if (ch2 === \"=\") {\n          this.emit(TokenType.LtEq, \"<=\", start, 2);\n          continue;\n        }\n        this.emit(TokenType.Lt, \"<\", start, 1);\n        continue;\n      }\n\n      // && before & (bitwise AND)\n      if (ch === \"&\") {\n        if (ch2 === \"&\") {\n          this.emit(TokenType.AmpAmp, \"&&\", start, 2);\n          continue;\n        }\n        this.emit(TokenType.Amp, \"&\", start, 1);\n        continue;\n      }\n\n      // || before | (bitwise OR)\n      if (ch === \"|\") {\n        if (ch2 === \"|\") {\n          this.emit(TokenType.PipePipe, \"||\", start, 2);\n          continue;\n        }\n        this.emit(TokenType.Pipe, \"|\", start, 1);\n        continue;\n      }\n\n      if (ch === \"^\") {\n        this.emit(TokenType.Caret, \"^\", start, 1);\n        continue;\n      }\n      if (ch === \"~\") {\n        this.emit(TokenType.Tilde, \"~\", start, 1);\n        continue;\n      }\n\n      // ?? before ?. before ?\n      if (ch === \"?\") {\n        if (ch2 === \"?\") {\n          this.emit(TokenType.QuestQuest, \"??\", start, 2);\n          continue;\n        }\n        // ?. \u2014 optional chaining. Per JS, ?. followed by a digit is two tokens (?, then .digit),\n        // but our lexer rejects bare leading-dot decimals anyway. Only emit ?. when a non-digit follows.\n        if (ch2 === \".\" && !this.isDigit(ch3)) {\n          this.emit(TokenType.QuestDot, \"?.\", start, 2);\n          continue;\n        }\n        this.emit(TokenType.Quest, \"?\", start, 1);\n        continue;\n      }\n\n      // ++ before += before +\n      if (ch === \"+\") {\n        if (ch2 === \"+\") {\n          this.emit(TokenType.PlusPlus, \"++\", start, 2);\n        } else if (ch2 === \"=\") {\n          this.emit(TokenType.PlusEq, \"+=\", start, 2);\n        } else {\n          this.emit(TokenType.Plus, \"+\", start, 1);\n        }\n        continue;\n      }\n      // -- before -= before -\n      if (ch === \"-\") {\n        if (ch2 === \"-\") {\n          this.emit(TokenType.MinusMinus, \"--\", start, 2);\n        } else if (ch2 === \"=\") {\n          this.emit(TokenType.MinusEq, \"-=\", start, 2);\n        } else {\n          this.emit(TokenType.Minus, \"-\", start, 1);\n        }\n        continue;\n      }\n      if (ch === \"%\") {\n        this.emit(TokenType.Percent, \"%\", start, 1);\n        continue;\n      }\n\n      // / \u2014 context-sensitive: divide (or /= compound) or regex literal\n      if (ch === \"/\") {\n        if (this.lastTokenType !== null && VALUE_ENDING_TYPES.has(this.lastTokenType)) {\n          if (ch2 === \"=\") {\n            this.emit(TokenType.SlashEq, \"/=\", start, 2);\n          } else {\n            this.emit(TokenType.Slash, \"/\", start, 1);\n          }\n        } else {\n          this.pushToken(this.readRegex(start));\n        }\n        continue;\n      }\n\n      // Numbers\n      if (this.isDigit(ch)) {\n        this.pushToken(this.readNumber(start));\n        continue;\n      }\n\n      // Strings\n      if (ch === '\"' || ch === \"'\") {\n        this.pushToken(this.readString(start));\n        continue;\n      }\n\n      // Template literal\n      if (ch === \"`\") {\n        this.pushToken({ type: TokenType.TemplateStart, value: \"`\", pos: start });\n        this.pos++; // consume opening `\n        this.readTemplateChunk(start);\n        continue;\n      }\n\n      // Identifiers / keywords\n      if (this.isIdentStart(ch)) {\n        const ident = this.readIdent();\n        const tok = this.keywordToken(ident, start);\n        this.pushToken(tok);\n        continue;\n      }\n\n      throw new LexError(`Unexpected character '${ch}' at position ${start}`, start);\n    }\n\n    this.tokens.push({ type: TokenType.EOF, value: \"\", pos: len });\n  }\n\n  private emit(type: TokenType, value: string, pos: number, len: number): void {\n    this.pushToken({ type, value, pos });\n    this.pos += len;\n  }\n\n  // ECMAScript LineTerminator set: U+000A (LF), U+000D (CR),\n  // U+2028 (LINE SEPARATOR), U+2029 (PARAGRAPH SEPARATOR).\n  // Use \\u escapes \u2014 LSEP/PSEP render invisibly in most editors.\n  private static readonly LINE_TERMINATORS = /[\\n\\r\\u2028\\u2029]/;\n\n  // Whitespace + JS-style comments. Both forms are pure trivia: discarded\n  // here, never reach the token stream or AST. Loop until neither pass\n  // makes progress, so any sequence of mixed whitespace and comments\n  // collapses to a single trivia run (matches JS).\n  private skipTrivia(): void {\n    while (this.pos < this.src.length) {\n      const before = this.pos;\n      while (this.pos < this.src.length && /\\s/.test(this.src[this.pos])) {\n        this.pos++;\n      }\n      if (this.pos < this.src.length && this.src[this.pos] === \"/\") {\n        const next = this.src[this.pos + 1];\n        if (next === \"/\") this.skipLineComment();\n        else if (next === \"*\") this.skipBlockComment();\n        else break;\n      }\n      if (this.pos === before) break;\n    }\n  }\n\n  // // line comments: skip until any LineTerminator or EOF. The terminator\n  // itself stays for the whitespace pass on the next skipTrivia iteration \u2014\n  // this keeps positional reporting honest and lets future line/column\n  // tracking count newlines in one place.\n  private skipLineComment(): void {\n    this.pos += 2;\n    while (this.pos < this.src.length && !Lexer.LINE_TERMINATORS.test(this.src[this.pos])) {\n      this.pos++;\n    }\n  }\n\n  // /* block comments */: scan for the closing */, EOF means unclosed.\n  // No nesting (matches JS \u2014 the first */ closes).\n  private skipBlockComment(): void {\n    const start = this.pos;\n    this.pos += 2;\n    while (this.pos + 1 < this.src.length) {\n      if (this.src[this.pos] === \"*\" && this.src[this.pos + 1] === \"/\") {\n        this.pos += 2;\n        return;\n      }\n      this.pos++;\n    }\n    throw new LexError(`Unclosed block comment starting at position ${start}`, start);\n  }\n\n  private isDigit(ch: string): boolean {\n    return ch >= \"0\" && ch <= \"9\";\n  }\n\n  private isIdentStart(ch: string): boolean {\n    return (ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\") || ch === \"_\";\n  }\n\n  private isIdentPart(ch: string): boolean {\n    return this.isIdentStart(ch) || this.isDigit(ch);\n  }\n\n  private readNumber(start: number): Token {\n    const src = this.src;\n    let i = this.pos;\n    i = this.consumeDigitsWithSeparators(i, start);\n    let hasFraction = false;\n    let hasExponent = false;\n    // Only consume the dot if the next char is also a digit \u2014 prevents 0.name being lexed as float\n    if (i < src.length && src[i] === \".\" && i + 1 < src.length && this.isDigit(src[i + 1])) {\n      hasFraction = true;\n      i++;\n      i = this.consumeDigitsWithSeparators(i, start);\n    }\n    if (i < src.length && (src[i] === \"e\" || src[i] === \"E\")) {\n      hasExponent = true;\n      i++;\n      if (i < src.length && (src[i] === \"+\" || src[i] === \"-\")) i++;\n      i = this.consumeDigitsWithSeparators(i, start);\n    }\n    // BigInt suffix: integer literals only. Reject `1.5n`, `1e2n`, etc. \u2014 matches JS.\n    if (i < src.length && src[i] === \"n\") {\n      if (hasFraction || hasExponent) {\n        throw new LexError(\n          `Invalid BigInt literal at position ${start}: 'n' suffix requires an integer (no fraction or exponent)`,\n          start,\n        );\n      }\n      const raw = src.slice(this.pos, i);\n      const value = raw.replace(/_/g, \"\");\n      this.pos = i + 1; // consume the 'n'\n      return { type: TokenType.BigInt, value, pos: start };\n    }\n    const raw = src.slice(this.pos, i);\n    // Numeric separators: strip underscores. _ is only valid between digits \u2014 readNumber\n    // never starts on _ (isIdentStart-routed), and consumeDigitsWithSeparators rejects\n    // trailing/adjacent underscores, so a simple replace is safe here.\n    const value = raw.replace(/_/g, \"\");\n    this.pos = i;\n    return { type: TokenType.Number, value, pos: start };\n  }\n\n  /**\n   * Consume a run of digits, allowing single underscores between them as numeric\n   * separators (1_000_000). Rejects leading, trailing, or doubled underscores.\n   */\n  private consumeDigitsWithSeparators(i: number, start: number): number {\n    const src = this.src;\n    if (i >= src.length || !this.isDigit(src[i])) return i;\n    i++;\n    while (i < src.length) {\n      const ch = src[i];\n      if (this.isDigit(ch)) {\n        i++;\n        continue;\n      }\n      if (ch === \"_\") {\n        const next = src[i + 1];\n        if (next === undefined || !this.isDigit(next)) {\n          throw new LexError(`Numeric separator '_' must be between two digits (at position ${i})`, start);\n        }\n        i++; // consume _\n        continue;\n      }\n      break;\n    }\n    return i;\n  }\n\n  private readString(start: number): Token {\n    const src = this.src;\n    const quote = src[this.pos];\n    this.pos++;\n    let result = \"\";\n    while (this.pos < src.length && src[this.pos] !== quote) {\n      if (src[this.pos] === \"\\\\\") {\n        this.pos++;\n        const esc = src[this.pos];\n        switch (esc) {\n          case \"n\":\n            result += \"\\n\";\n            break;\n          case \"t\":\n            result += \"\\t\";\n            break;\n          case \"r\":\n            result += \"\\r\";\n            break;\n          case \"\\\\\":\n            result += \"\\\\\";\n            break;\n          case '\"':\n            result += '\"';\n            break;\n          case \"'\":\n            result += \"'\";\n            break;\n          default:\n            result += esc;\n        }\n      } else {\n        result += src[this.pos];\n      }\n      this.pos++;\n    }\n    if (this.pos >= src.length) {\n      throw new LexError(`Unterminated string at position ${start}`, start);\n    }\n    this.pos++;\n    return { type: TokenType.String, value: result, pos: start };\n  }\n\n  /**\n   * Read a chunk of a template literal \u2014 characters between the previous boundary\n   * (opening `, or `${...}`) and the next boundary (closing `, or `${`).\n   *\n   * Always emits a TemplateChars token (possibly empty) followed by either:\n   *   - TemplateExprStart for `${`, then returns to caller (main lex loop resumes\n   *     normal lexing inside the expression \u2014 the matching `}` re-enters this method)\n   *   - TemplateEnd for closing backtick, then returns\n   */\n  private readTemplateChunk(initialStart: number): void {\n    const src = this.src;\n    const chunkStart = this.pos;\n    let result = \"\";\n    while (this.pos < src.length) {\n      const ch = src[this.pos];\n      if (ch === \"`\") {\n        this.pushToken({ type: TokenType.TemplateChars, value: result, pos: chunkStart });\n        this.pushToken({ type: TokenType.TemplateEnd, value: \"`\", pos: this.pos });\n        this.pos++;\n        return;\n      }\n      if (ch === \"$\" && src[this.pos + 1] === \"{\") {\n        this.pushToken({ type: TokenType.TemplateChars, value: result, pos: chunkStart });\n        this.pushToken({ type: TokenType.TemplateExprStart, value: \"${\", pos: this.pos });\n        this.pos += 2;\n        this.templateBraceDepths.push(this.braceDepth);\n        return;\n      }\n      if (ch === \"\\\\\") {\n        this.pos++;\n        const esc = src[this.pos];\n        switch (esc) {\n          case \"n\":\n            result += \"\\n\";\n            break;\n          case \"t\":\n            result += \"\\t\";\n            break;\n          case \"r\":\n            result += \"\\r\";\n            break;\n          case \"\\\\\":\n            result += \"\\\\\";\n            break;\n          case \"`\":\n            result += \"`\";\n            break;\n          case \"$\":\n            result += \"$\";\n            break;\n          default:\n            result += esc;\n        }\n        this.pos++;\n        continue;\n      }\n      result += ch;\n      this.pos++;\n    }\n    throw new LexError(`Unterminated template literal at position ${initialStart}`, initialStart);\n  }\n\n  private readRegex(start: number): Token {\n    const src = this.src;\n    this.pos++; // consume opening /\n    let pattern = \"\";\n    let inClass = false; // inside [...] character class\n\n    while (this.pos < src.length) {\n      const ch = src[this.pos];\n      if (ch === \"\\\\\") {\n        // Escape sequence \u2014 consume both chars\n        this.pos++;\n        if (this.pos < src.length) {\n          pattern += \"\\\\\" + src[this.pos];\n          this.pos++;\n        }\n        continue;\n      }\n      if (ch === \"[\") {\n        inClass = true;\n        pattern += ch;\n        this.pos++;\n        continue;\n      }\n      if (ch === \"]\") {\n        inClass = false;\n        pattern += ch;\n        this.pos++;\n        continue;\n      }\n      if (ch === \"/\" && !inClass) {\n        this.pos++; // consume closing /\n        break;\n      }\n      if (ch === \"\\n\") {\n        throw new LexError(`Unterminated regex literal at position ${start}`, start);\n      }\n      pattern += ch;\n      this.pos++;\n    }\n\n    // Read optional flags\n    let flags = \"\";\n    while (this.pos < src.length && /[gimsuy]/.test(src[this.pos])) {\n      flags += src[this.pos];\n      this.pos++;\n    }\n\n    return { type: TokenType.RegexLiteral, value: pattern, flags, pos: start };\n  }\n\n  private readIdent(): string {\n    const src = this.src;\n    let i = this.pos;\n    while (i < src.length && this.isIdentPart(src[i])) i++;\n    const ident = src.slice(this.pos, i);\n    this.pos = i;\n    return ident;\n  }\n\n  private keywordToken(ident: string, pos: number): Token {\n    switch (ident) {\n      case \"true\":\n        return { type: TokenType.True, value: \"true\", pos };\n      case \"false\":\n        return { type: TokenType.False, value: \"false\", pos };\n      case \"null\":\n        return { type: TokenType.Null, value: \"null\", pos };\n      case \"undefined\":\n        return { type: TokenType.Undefined, value: \"undefined\", pos };\n      case \"in\":\n        return { type: TokenType.In, value: \"in\", pos };\n      case \"new\":\n        return { type: TokenType.New, value: \"new\", pos };\n      case \"typeof\":\n        return { type: TokenType.Typeof, value: \"typeof\", pos };\n      case \"delete\":\n        return { type: TokenType.Delete, value: \"delete\", pos };\n      case \"let\":\n        return { type: TokenType.Let, value: \"let\", pos };\n      default:\n        return { type: TokenType.Ident, value: ident, pos };\n    }\n  }\n}\n", "// Cheap Levenshtein distance + closest-name lookup. Used to power \"did you\n// mean?\" suggestions in error messages \u2014 pipeline-stage typos and unknown\n// method names today.\n\nexport function levenshtein(a: string, b: string): number {\n  const m = a.length;\n  const n = b.length;\n  if (m === 0) return n;\n  if (n === 0) return m;\n  const prev = new Array<number>(n + 1);\n  const curr = new Array<number>(n + 1);\n  for (let j = 0; j <= n; j++) prev[j] = j;\n  for (let i = 1; i <= m; i++) {\n    curr[0] = i;\n    for (let j = 1; j <= n; j++) {\n      const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1;\n      curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);\n    }\n    for (let j = 0; j <= n; j++) prev[j] = curr[j];\n  }\n  return prev[n];\n}\n\n/**\n * Find the candidate string closest to `name` by edit distance. Returns null\n * when no candidate is close enough to be a likely typo (max 2 edits, and the\n * distance must be strictly less than the input's own length so a totally\n * unrelated short name doesn't trigger).\n */\nexport function closestNameTo(name: string, candidates: Iterable<string>): string | null {\n  let best: { name: string; dist: number } | null = null;\n  for (const candidate of candidates) {\n    const d = levenshtein(name, candidate);\n    if (best === null || d < best.dist) best = { name: candidate, dist: d };\n  }\n  if (best === null) return null;\n  if (best.dist <= 2 && best.dist < name.length) return best.name;\n  return null;\n}\n\n/**\n * Build the trailing \" Did you mean 'X'?\" hint for a rejection against a closed\n * set of names \u2014 the canonical way to satisfy the closest-name DX mandate (see\n * the error-consistency rules in CLAUDE.md). Returns \"\" when no candidate is\n * close enough, so the call site can interpolate the result unconditionally.\n *\n * `format` renders the suggestion the way the surrounding message spells the\n * name: the default is the instance-method form (`.foo()`); pass\n * `(s) => \\`Class.\\${s}\\`` for statics, or `(s) => s` for bare names (stages).\n */\nexport function didYouMean(\n  name: string,\n  candidates: Iterable<string>,\n  format: (s: string) => string = (s) => `.${s}()`,\n): string {\n  const suggestion = closestNameTo(name, candidates);\n  return suggestion ? ` Did you mean '${format(suggestion)}'?` : \"\";\n}\n", "export type SpreadElement = { type: \"SpreadElement\"; argument: Expr; pos: number };\n\nexport type StaticKey = { kind: \"static\"; name: string };\nexport type ComputedKey = { kind: \"computed\"; expr: Expr };\nexport type ObjectKey = StaticKey | ComputedKey;\n\nexport type KeyValueEntry = { type: \"KeyValueEntry\"; key: ObjectKey; value: Expr; pos: number };\n\nexport type ObjectEntry = KeyValueEntry | SpreadElement;\n// AssignExpr, DeleteStmt, and LetDecl are valid as ArrayElements ONLY when the\n// array is a pipeline (first element is a stage candidate). Codegen for a\n// non-pipeline ArrayLiteral throws on these \u2014 see codegen.ts:generateArrayLiteral.\nexport type ArrayElement = Expr | SpreadElement | AssignExpr | DeleteStmt | LetDecl;\n\n/** Argument position that may be a spread (call sites that allow `...x`) */\nexport type CallArg = Expr | SpreadElement;\n\n/**\n * Assignment statement: `$.path = value` (also reached via `+=`/`-=`/`*=`/`/=`,\n * which the parser desugars into a `=` plus the corresponding `BinaryExpr`).\n * `target` is restricted to a field-path expression (FieldRef or chained\n * MemberAccess rooted at a FieldRef); the parser enforces this at construction.\n */\nexport type AssignExpr = { type: \"AssignExpr\"; target: Expr; value: Expr; pos: number };\n\n/** Statement form: `delete $.path`. Only legal at top level or as a pipeline element. */\nexport type DeleteStmt = { type: \"DeleteStmt\"; target: Expr; pos: number };\n\nexport type UpdateOp = AssignExpr | DeleteStmt;\n\n/**\n * Pipeline-scoped local binding: `let <name> = <value>`. Only valid at the top\n * level of a pipeline (either as a `;`-separated PipelineStmt or as an element\n * inside a bracketed `[...]` pipeline). The value is materialised under a\n * single compiler-owned namespace (`__jsmql.<name>`) and the namespace is\n * `$unset` at the end of the pipeline. See `docs/specs/let-bindings.md`.\n */\nexport type LetDecl = { type: \"LetDecl\"; name: string; value: Expr; pos: number };\n\n/**\n * Top-level **update filter**: one or more assignments and/or deletes,\n * separated by `,` in source. Lowers to a MongoDB Update Filter document\n * (the `{ $set: \u2026, $unset: \u2026 }` shape passed as the second argument to\n * `db.coll.updateOne(filter, update)`). Distinct from `Expr` because the\n * constituent statements have document-level effect, not expression values.\n *\n * `;` is reserved for the top-level pipeline separator (see `Pipeline`)\n * and is not an update-filter separator.\n */\nexport type UpdateFilter = { type: \"UpdateFilter\"; ops: UpdateOp[]; pos: number };\n\n/**\n * One element of an implicit pipeline (`;`-separated at top level). Each\n * element is lowered in isolation \u2014 an `UpdateFilter` may itself emit\n * multiple stages (read-after-write splits inside a `,`-grouped chain),\n * but adjacent elements never coalesce. `LetDecl` contributes one `$set`\n * stage plus a binding visible to subsequent statements (see\n * `generateImplicitPipeline`).\n */\nexport type PipelineStmt = UpdateFilter | Expr | LetDecl;\n\n/**\n * Top-level pipeline assembled from `;`-separated statements. Distinct from\n * `ArrayLiteral`-shaped pipelines (`[...]`) because elements come pre-grouped\n * into stages and must NOT cross-coalesce. See `generateImplicitPipeline`.\n */\nexport type Pipeline = { type: \"Pipeline\"; stmts: PipelineStmt[]; pos: number };\n\n/** What `Parser.parse()` returns: an expression, an update filter, or a `;`-separated pipeline. */\nexport type Program = Expr | UpdateFilter | Pipeline;\n\nexport type BinaryOp =\n  | \"+\"\n  | \"-\"\n  | \"*\"\n  | \"/\"\n  | \"%\"\n  | \"**\"\n  | \"==\"\n  | \"!=\"\n  | \"===\"\n  | \"!==\"\n  | \">\"\n  | \">=\"\n  | \"<\"\n  | \"<=\"\n  | \"&\"\n  | \"|\"\n  | \"^\"\n  | \"&&\"\n  | \"||\"\n  | \"??\"\n  | \"in\";\n\nexport type UnaryOp = \"!\" | \"-\" | \"~\";\n\nexport type Expr =\n  | {\n      type: \"OperatorCall\";\n      name: string;\n      /** positional = args are expressions; object = single ObjectLiteral arg */\n      style: \"positional\" | \"object\";\n      args: CallArg[];\n      pos: number;\n    }\n  | { type: \"FieldRef\"; path: string; pos: number }\n  | { type: \"CollectionRef\"; pos: number } // $$  \u2014 postfix `.name` / `[expr]` composes via MemberAccess / IndexAccess\n  | { type: \"DatabaseRef\"; pos: number } //   $$$\n  | { type: \"ClusterRef\"; pos: number } //    $$$$\n  | { type: \"NumberLiteral\"; value: number; pos: number }\n  | { type: \"BigIntLiteral\"; value: string; pos: number }\n  | { type: \"StringLiteral\"; value: string; pos: number }\n  | { type: \"BooleanLiteral\"; value: boolean; pos: number }\n  | { type: \"NullLiteral\"; pos: number }\n  | { type: \"UndefinedLiteral\"; pos: number }\n  | { type: \"ArrayLiteral\"; elements: ArrayElement[]; pos: number }\n  | { type: \"ObjectLiteral\"; entries: ObjectEntry[]; pos: number }\n  | { type: \"TemplateLiteral\"; quasis: string[]; expressions: Expr[]; pos: number }\n  | { type: \"BinaryExpr\"; op: BinaryOp; left: Expr; right: Expr; pos: number }\n  | { type: \"UnaryExpr\"; op: UnaryOp; operand: Expr; pos: number }\n  | { type: \"TernaryExpr\"; condition: Expr; consequent: Expr; alternate: Expr; pos: number }\n  | { type: \"IndexAccess\"; object: Expr; index: Expr; pos: number; optional?: boolean }\n  | { type: \"RegexLiteral\"; pattern: string; flags: string; pos: number }\n  | { type: \"ParamRef\"; name: string; pos: number }\n  | { type: \"MemberAccess\"; object: Expr; member: string; pos: number; optional?: boolean }\n  | { type: \"MethodCall\"; object: Expr; method: string; args: CallArg[]; pos: number; optional?: boolean }\n  | { type: \"CallExpression\"; callee: Expr; args: CallArg[]; pos: number }\n  | { type: \"Lambda\"; params: string[]; body?: Expr; block?: Pipeline; pos: number }\n  | { type: \"TypeofExpr\"; operand: Expr; pos: number }\n  | { type: \"NewDate\"; args: Expr[]; pos: number }\n  | { type: \"NewSet\"; arg: Expr | null; pos: number }\n  | { type: \"TypeCast\"; cast: TypeCastOp; arg: Expr; pos: number }\n  | { type: \"TypeCastRef\"; cast: BareCastOp; pos: number }\n  | { type: \"MathCall\"; method: MathMethod; args: CallArg[]; pos: number }\n  | { type: \"MathCallRef\"; method: MathMethod; pos: number }\n  | { type: \"MathConst\"; name: MathConstant; pos: number }\n  | { type: \"ObjectCall\"; method: ObjectMethod; args: CallArg[]; pos: number }\n  | { type: \"ArrayFrom\"; input: Expr; mapFn: Expr | null; pos: number }\n  | { type: \"NumberStatic\"; method: NumberStaticMethod; arg: Expr; pos: number }\n  | { type: \"DateNow\"; pos: number }\n  | { type: \"DateUTC\"; args: Expr[]; pos: number };\n\nexport type TypeCastOp = \"Number\" | \"String\" | \"Boolean\" | \"parseInt\" | \"parseFloat\";\n/** Type-cast names usable as bare callbacks (e.g. `arr.filter(Boolean)`).\n * Excludes parseInt/parseFloat because real-JS `arr.map(parseInt)` has the\n * famous index-as-radix footgun; users must write `x => parseInt(x)` to opt in. */\nexport type BareCastOp = \"Number\" | \"String\" | \"Boolean\";\n// \u2500\u2500 Recognised JS-builtin static/constructor names \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Single source of truth for each closed name-set: the parser validates against\n// these (and builds its `didYouMean` candidate lists from them), and codegen\n// derives its dispatch signatures from the matching `\u2026Method` type. Each list is\n// `as const` so the derived union stays exhaustiveness-checked at the codegen\n// switch \u2014 adding a name here surfaces a missing-case compile error there.\nexport const MATH_METHODS = [\n  \"abs\",\n  \"ceil\",\n  \"floor\",\n  \"round\",\n  \"pow\",\n  \"sqrt\",\n  \"exp\",\n  \"log\",\n  \"log2\",\n  \"log10\",\n  \"trunc\",\n  \"min\",\n  \"max\",\n  \"sign\",\n  \"hypot\",\n  \"cbrt\",\n  \"random\",\n  \"sin\",\n  \"cos\",\n  \"tan\",\n  \"asin\",\n  \"acos\",\n  \"atan\",\n  \"atan2\",\n  \"sinh\",\n  \"cosh\",\n  \"tanh\",\n  \"asinh\",\n  \"acosh\",\n  \"atanh\",\n] as const;\nexport type MathMethod = (typeof MATH_METHODS)[number];\n\nexport const MATH_CONSTANTS = [\"PI\", \"E\"] as const;\nexport type MathConstant = (typeof MATH_CONSTANTS)[number];\n\nexport const OBJECT_METHODS = [\"keys\", \"values\", \"entries\", \"assign\", \"fromEntries\", \"groupBy\"] as const;\nexport type ObjectMethod = (typeof OBJECT_METHODS)[number];\n\nexport const NUMBER_STATICS = [\"isInteger\", \"isNaN\", \"isFinite\"] as const;\nexport type NumberStaticMethod = (typeof NUMBER_STATICS)[number];\n\n// Set-receiver methods jsmql lowers to `$setIntersection` / `$setUnion` / etc.\n// Previously the canonical list lived only in a codegen error string.\nexport const SET_METHODS = [\"intersection\", \"union\", \"difference\", \"isSubsetOf\", \"isSupersetOf\"] as const;\nexport type SetMethod = (typeof SET_METHODS)[number];\n", "import { Lexer, TokenType, type Token } from \"./lexer.ts\";\nimport { didYouMean } from \"./levenshtein.ts\";\nimport {\n  MATH_METHODS as MATH_METHOD_NAMES,\n  MATH_CONSTANTS as MATH_CONSTANT_NAMES,\n  OBJECT_METHODS as OBJECT_METHOD_NAMES,\n  NUMBER_STATICS,\n} from \"./ast.ts\";\nimport type {\n  Expr,\n  BinaryOp,\n  ArrayElement,\n  ObjectEntry,\n  KeyValueEntry,\n  SpreadElement,\n  TypeCastOp,\n  BareCastOp,\n  MathMethod,\n  MathConstant,\n  ObjectMethod,\n  NumberStaticMethod,\n  ObjectKey,\n  CallArg,\n  AssignExpr,\n  DeleteStmt,\n  LetDecl,\n  UpdateOp,\n  UpdateFilter,\n  Pipeline,\n  PipelineStmt,\n  Program,\n} from \"./ast.ts\";\n\nexport class ParseError extends Error {\n  readonly pos: number;\n  constructor(message: string, pos: number) {\n    super(message);\n    this.name = \"ParseError\";\n    this.pos = pos;\n  }\n}\n\n/**\n * Raised by `Parser.parseFunctionInput()` when the source given to\n * `jsmql(($) => \u2026)` is not a valid arrow function shape \u2014 `async`\n * arrows, `function` declarations, missing arrow operator, unbalanced\n * params, `return` inside a block body, etc. Distinct from `ParseError`\n * because the failure is in the function-shape adapter, not in jsmql's\n * own grammar; `validate()` maps both to `SYNTAX_ERROR`.\n */\nexport class FunctionInputError extends Error {\n  readonly pos: number;\n  constructor(message: string, pos: number = 0) {\n    super(message);\n    this.name = \"FunctionInputError\";\n    this.pos = pos;\n  }\n}\n\n/**\n * One entry in the params destructure of a function-form arrow.\n * - `key` is the property looked up on the params object at call time\n *   (the *outer* destructure key).\n * - `name` is the identifier used in the function body (the *inner* alias if\n *   the user wrote `{ key: alias }`, or the same as `key` otherwise).\n *\n * Most users never alias and both fields are identical; aliasing exists so a\n * verbose public param name can have a short body-local synonym.\n */\nexport type ParamBinding = { key: string; name: string };\n\n/**\n * Result of `Parser.parseFunctionInput()`. The function source is split into a\n * parsed body (`program`) and the parameter bindings extracted from the params\n * slot (`bindings`, empty when the arrow has no params destructure). The two\n * pieces travel together because codegen needs the binding names to interpret\n * bare identifiers in the body as parameter references rather than unknown\n * idents.\n */\nexport type FunctionInputResult = { program: Program; bindings: ParamBinding[] };\n\n/**\n * Math methods that take exactly one argument \u2014 the only subset that can be\n * passed as a bare callable (e.g. `arr.map(Math.floor)`). Mirrors the JS\n * unary signatures. Binary methods (`pow`, `min`, `max`, `hypot`, `atan2`)\n * and the zero-arg `random` require explicit parens to avoid arity\n * ambiguity when used as callbacks.\n */\nconst UNARY_MATH_CALLABLES = new Set<string>([\n  \"abs\",\n  \"ceil\",\n  \"floor\",\n  \"round\",\n  \"sqrt\",\n  \"exp\",\n  \"log\",\n  \"log2\",\n  \"log10\",\n  \"trunc\",\n  \"sign\",\n  \"cbrt\",\n  \"sin\",\n  \"cos\",\n  \"tan\",\n  \"asin\",\n  \"acos\",\n  \"atan\",\n  \"sinh\",\n  \"cosh\",\n  \"tanh\",\n]);\n\n// Runtime lookup Sets built from the single-source name lists in ast.ts.\nconst MATH_METHODS = new Set<string>(MATH_METHOD_NAMES);\nconst MATH_CONSTANTS = new Set<string>(MATH_CONSTANT_NAMES);\nconst OBJECT_METHODS = new Set<string>(OBJECT_METHOD_NAMES);\n\nconst TYPE_CAST_NAMES = new Set<string>([\"Number\", \"String\", \"Boolean\", \"parseInt\", \"parseFloat\"]);\n// Subset of TYPE_CAST_NAMES that are also valid as bare callbacks:\n//   $.items.filter(Boolean) === $.items.filter(x => Boolean(x))\n// parseInt / parseFloat are excluded so we don't import the JS\n// `arr.map(parseInt)` index-as-radix footgun \u2014 users opt in explicitly with\n// `x => parseInt(x)`.\nconst BARE_CAST_NAMES = new Set<BareCastOp>([\"Number\", \"String\", \"Boolean\"]);\n\nfunction compoundBinaryOp(op: \"+=\" | \"-=\" | \"*=\" | \"/=\"): BinaryOp {\n  switch (op) {\n    case \"+=\":\n      return \"+\";\n    case \"-=\":\n      return \"-\";\n    case \"*=\":\n      return \"*\";\n    case \"/=\":\n      return \"/\";\n  }\n}\n\n// Recursion-depth cap for the recursive-descent parser. Each user-visible\n// nest level burns ~17 stack frames as the precedence cascade walks from\n// parseExpression down to parsePrimary; 200 levels stays well within Node's\n// default stack budget while comfortably above any realistic expression.\n// Exceeding it surfaces a structured ParseError instead of an uncaught\n// V8 RangeError. Mirrored in codegen.ts.\nexport const MAX_RECURSION_DEPTH = 200;\n\nexport class Parser {\n  private readonly lexer: Lexer;\n  private depth = 0;\n\n  constructor(src: string) {\n    this.lexer = new Lexer(src);\n  }\n\n  parse(): Program {\n    // Top-level grammar:\n    //   program := stmt (\";\" stmt)* \";\"?\n    // where each `stmt` is either an expression or a update op chain (one or\n    // more comma-separated update ops). Any presence of `;` \u2014 including a\n    // single trailing one \u2014 flips the input to pipeline mode (`Pipeline`),\n    // and each `;`-separated chunk becomes its own stage(s) in the lowerer\n    // with no cross-coalescing. Without any `;`, behaviour is unchanged:\n    // the single statement is returned as `Expr` or `UpdateFilter`.\n    const stmts: PipelineStmt[] = [this.collectStatement()];\n    let sawSemi = false;\n    while (this.lexer.peek().type === TokenType.Semi) {\n      this.lexer.next(); // consume `;`\n      sawSemi = true;\n      if (this.lexer.peek().type === TokenType.EOF) break; // trailing `;`\n      stmts.push(this.collectStatement());\n    }\n\n    const eof = this.lexer.peek();\n    if (eof.type !== TokenType.EOF) {\n      throw new ParseError(`Unexpected token '${eof.value}' at position ${eof.pos}`, eof.pos);\n    }\n\n    if (!sawSemi) {\n      const only = stmts[0];\n      if (only.type === \"LetDecl\") this.throwLetOutsidePipeline(only.name, only.pos);\n      return only;\n    }\n    return { type: \"Pipeline\", stmts, pos: stmts[0].pos };\n  }\n\n  /**\n   * Entry point for the function-input form (`jsmql(($) => \u2026)`). The source\n   * is the result of `Function.prototype.toString.call(fn)` \u2014 a full arrow\n   * function expression. We consume the parameter list and `=>`, then dispatch\n   * to either a block-body parser (`{ stmt; stmt; }`, the function-form mirror\n   * of the implicit `;`-separated pipeline) or an expression-body parser (a\n   * single jsmql expression / update op, with one optional trailing `;` allowed\n   * as a formatter artifact \u2014 single-statement bodies do NOT flip into pipeline\n   * mode here).\n   *\n   * Raises `FunctionInputError` for shape problems specific to the adapter\n   * (`async`, `function`, missing arrow, `return` in a block body, \u2026) and\n   * `ParseError`/`LexError` for grammar problems inside the body itself.\n   */\n  parseFunctionInput(): FunctionInputResult {\n    const first = this.lexer.peek();\n    if (first.type === TokenType.Ident && first.value === \"async\") {\n      throw new FunctionInputError(\n        \"jsmql does not support async functions. Use a synchronous arrow: `($) => \u2026`\",\n        first.pos,\n      );\n    }\n    if (first.type === TokenType.Ident && first.value === \"function\") {\n      throw new FunctionInputError(\n        \"jsmql expects an arrow function, got a `function` declaration. Use: `($) => \u2026`\",\n        first.pos,\n      );\n    }\n    if (first.type !== TokenType.LParen) {\n      throw new FunctionInputError(\"jsmql expects an arrow function `($) => \u2026` as the function-form input.\", first.pos);\n    }\n    const bindings = this.parseParameterList();\n\n    const arrowTok = this.lexer.peek();\n    if (arrowTok.type !== TokenType.Arrow) {\n      throw new FunctionInputError(\n        \"jsmql could not find an arrow operator (`=>`) in the function source. Use: `($) => \u2026`\",\n        arrowTok.pos,\n      );\n    }\n    this.lexer.next(); // consume `=>`\n\n    const program = this.lexer.peek().type === TokenType.LBrace ? this.parseBlockBody() : this.parseExpressionBody();\n    return { program, bindings };\n  }\n\n  /**\n   * Parse and classify the parenthesised parameter list of the function-form\n   * arrow. Each top-level parameter slot is one of three *shapes*:\n   *\n   *   - **Plain identifier** (`$`, `doc`, anything) \u2014 the document-context slot.\n   *     Discarded; the body parser doesn't need the name.\n   *   - **Destructure pattern with all keys starting with `$`** (`{ $dateDiff }`,\n   *     `{ $match, $project }`) \u2014 the ops-hint slot (types-only IDE\n   *     autocomplete). Discarded; the keys don't reach codegen.\n   *   - **Destructure pattern with at least one non-`$` key** (`{ minAge }`) \u2014\n   *     the function-form parameter bindings. Names are returned so codegen can\n   *     inline values supplied at `jsmql.compile()` call time.\n   *\n   * The legal slot orderings are: `()`, `(doc)`, `(ops)`, `(params)`,\n   * `(doc, ops)`, `(params, doc)`, `(params, ops)`, `(params, doc, ops)`.\n   * Anything else throws `FunctionInputError` with a precise message.\n   *\n   * Returns the binding names extracted from the params slot (in source\n   * order). Cursor is left immediately after the closing `)`.\n   */\n  private parseParameterList(): ParamBinding[] {\n    this.lexer.next(); // consume opening `(`\n\n    type Slot =\n      | { kind: \"doc\"; pos: number }\n      | { kind: \"ops\"; pos: number }\n      | { kind: \"params\"; bindings: ParamBinding[]; pos: number };\n    const slots: Slot[] = [];\n\n    if (this.lexer.peek().type !== TokenType.RParen) {\n      while (true) {\n        slots.push(this.parseParameterSlot());\n        const sep = this.lexer.peek();\n        if (sep.type === TokenType.Comma) {\n          this.lexer.next();\n          continue;\n        }\n        if (sep.type === TokenType.RParen) break;\n        throw new FunctionInputError(\n          `jsmql could not parse the function parameter list \u2014 expected ',' or ')' at position ${sep.pos}, got '${sep.value}'.`,\n          sep.pos,\n        );\n      }\n    }\n    const closeParen = this.lexer.next(); // consume `)`\n\n    if (slots.length > 3) {\n      throw new FunctionInputError(\n        `jsmql's compile-form arrow takes at most three parameters in the order \\`(params, $, opsHint)\\`. ` +\n          `Got ${slots.length} parameters. Reorder to \\`(params, $, opsHint)\\` and drop any extras.`,\n        closeParen.pos,\n      );\n    }\n\n    // Validate slot ordering. The legal orderings are: each slot kind appears\n    // at most once, and the order (when all present) is params \u2192 doc \u2192 ops.\n    let sawParams = false;\n    let sawDoc = false;\n    let sawOps = false;\n    let bindings: ParamBinding[] = [];\n    for (const slot of slots) {\n      if (slot.kind === \"params\") {\n        if (sawParams) {\n          throw new FunctionInputError(\n            \"jsmql params destructure may only appear once. Combine the bindings into a single parameter: `({ a, b }, \u2026) => \u2026`.\",\n            slot.pos,\n          );\n        }\n        if (sawDoc || sawOps) {\n          throw new FunctionInputError(\n            \"jsmql expects the params destructure to appear before the `$` doc-context parameter and the ops-hint destructure. \" +\n              \"Reorder to `(params, $, opsHint)`.\",\n            slot.pos,\n          );\n        }\n        sawParams = true;\n        bindings = slot.bindings;\n      } else if (slot.kind === \"doc\") {\n        if (sawDoc) {\n          throw new FunctionInputError(\n            \"jsmql's compile-form arrow takes at most one document-context parameter (`$`).\",\n            slot.pos,\n          );\n        }\n        if (sawOps) {\n          throw new FunctionInputError(\n            \"jsmql expects the `$` doc-context parameter to appear before the ops-hint destructure. \" +\n              \"Reorder to `(params, $, opsHint)`.\",\n            slot.pos,\n          );\n        }\n        sawDoc = true;\n      } else {\n        if (sawOps) {\n          throw new FunctionInputError(\n            \"jsmql's compile-form arrow takes at most one ops-hint destructure (e.g. `{ $match }`).\",\n            slot.pos,\n          );\n        }\n        sawOps = true;\n      }\n    }\n    return bindings;\n  }\n\n  /**\n   * Parse a single parameter slot and classify it by shape. Called by\n   * `parseParameterList`; advances the lexer past the slot.\n   */\n  private parseParameterSlot():\n    | { kind: \"doc\"; pos: number }\n    | { kind: \"ops\"; pos: number }\n    | { kind: \"params\"; bindings: ParamBinding[]; pos: number } {\n    const head = this.lexer.peek();\n    if (head.type === TokenType.LBracket) {\n      throw new FunctionInputError(\n        \"jsmql params must be an object destructure pattern: `{ a, b }`. \" +\n          \"Array destructure is not accepted \u2014 params are always named, never positional.\",\n        head.pos,\n      );\n    }\n    if (head.type === TokenType.Ident) {\n      // Plain-identifier slot \u2014 discard the name.\n      this.lexer.next();\n      return { kind: \"doc\", pos: head.pos };\n    }\n    if (head.type === TokenType.Dollar) {\n      // Plain `$` identifier in the doc slot.\n      this.lexer.next();\n      return { kind: \"doc\", pos: head.pos };\n    }\n    if (head.type !== TokenType.LBrace) {\n      throw new FunctionInputError(\n        `jsmql expects each parameter to be an identifier or an object destructure pattern. Got '${head.value}' at position ${head.pos}.`,\n        head.pos,\n      );\n    }\n    return this.parseDestructureSlot();\n  }\n\n  /**\n   * Parse `{ key (: alias)? (, key)* (,)? }` and classify the slot as `ops`\n   * (every key starts with `$`) or `params` (at least one non-`$` key).\n   * Rejects defaults, nested destructure, rest, and mixed `$`/non-`$` keys\n   * with the user-facing error messages from `docs/LANGUAGE.md`.\n   */\n  private parseDestructureSlot():\n    | { kind: \"ops\"; pos: number }\n    | { kind: \"params\"; bindings: ParamBinding[]; pos: number } {\n    const openBrace = this.lexer.next(); // consume `{`\n    const opsKeys: string[] = [];\n    const paramBindings: ParamBinding[] = [];\n\n    if (this.lexer.peek().type === TokenType.RBrace) {\n      // Empty destructure \u2014 treat as ops-hint (no-op).\n      this.lexer.next();\n      return { kind: \"ops\", pos: openBrace.pos };\n    }\n\n    while (true) {\n      const key = this.lexer.peek();\n      if (key.type === TokenType.Spread) {\n        throw new FunctionInputError(\n          \"jsmql does not support rest patterns in params: `{ ...rest }`. \" +\n            \"The set of bindings must be statically known at compile time so the generated MQL can reference each by name. \" +\n            \"List each binding explicitly: `{ a, b, c }`.\",\n          key.pos,\n        );\n      }\n      // Either `$name` (Dollar followed by Ident) for ops-hint keys, or\n      // `name` (Ident) for params keys.\n      let keyName: string;\n      let isOpsKey: boolean;\n      if (key.type === TokenType.Dollar) {\n        this.lexer.next();\n        const ident = this.lexer.peek();\n        if (ident.type !== TokenType.Ident) {\n          throw new FunctionInputError(\n            `jsmql expected an identifier after '$' in the destructure key at position ${ident.pos}.`,\n            ident.pos,\n          );\n        }\n        this.lexer.next();\n        keyName = `$${ident.value}`;\n        isOpsKey = true;\n      } else if (key.type === TokenType.Ident) {\n        this.lexer.next();\n        keyName = key.value;\n        isOpsKey = false;\n      } else {\n        throw new FunctionInputError(\n          `jsmql expected an identifier in the destructure pattern at position ${key.pos}, got '${key.value}'.`,\n          key.pos,\n        );\n      }\n\n      // Optional alias: `{ key: alias }`. Used for params keys to give the\n      // body identifier a different (usually shorter) name than the param\n      // object property name. Ignored for ops keys \u2014 the alias would only\n      // serve IDE autocomplete, which the original key already provides.\n      let bindingName = keyName;\n      if (this.lexer.peek().type === TokenType.Colon) {\n        this.lexer.next(); // consume `:`\n        const alias = this.lexer.peek();\n        if (alias.type === TokenType.LBrace || alias.type === TokenType.LBracket) {\n          throw new FunctionInputError(\n            \"jsmql does not support nested destructure in params: `{ <name>: { \u2026 } }`. \" +\n              \"Params is a flat key\u2192value map at the MQL level. Use a single level of destructure and reference nested fields explicitly at the call site, e.g. `q({ b: source.a.b })`.\",\n            alias.pos,\n          );\n        }\n        if (alias.type !== TokenType.Ident) {\n          throw new FunctionInputError(\n            `jsmql expected an alias identifier after ':' in the destructure pattern at position ${alias.pos}, got '${alias.value}'.`,\n            alias.pos,\n          );\n        }\n        this.lexer.next();\n        bindingName = alias.value;\n      }\n\n      // Optional default: `{ key = expr }` \u2014 always rejected.\n      if (this.lexer.peek().type === TokenType.Eq) {\n        const defaultTok = this.lexer.peek();\n        throw new FunctionInputError(\n          \"jsmql does not support default values in the params destructure: `{ <name> = <expr> }`.\\n\\n\" +\n            \"jsmql compiles your function to MQL at parse time. It reads the function's source text but cannot evaluate the default expression \u2014 for `= config.minAge` or `= Date.now()` there is no runtime to ask, since jsmql never actually calls your arrow. Restricting defaults to literals (`= 18`) would make the rule silently inconsistent with the rest of the destructure, where any value is fine at call time.\\n\\n\" +\n            \"Instead:\\n\" +\n            \"  - For a runtime fallback, use JS's `??` at the call site: `q({ minAge: input ?? 18 })`.\\n\" +\n            \"  - For a value that's always the same and never overridden, the template-tag form already inlines hardcoded values: `` jsmql`$.age > ${18}` ``.\",\n          defaultTok.pos,\n        );\n      }\n\n      if (isOpsKey) opsKeys.push(keyName);\n      else paramBindings.push({ key: keyName, name: bindingName });\n\n      const sep = this.lexer.peek();\n      if (sep.type === TokenType.Comma) {\n        this.lexer.next();\n        // Allow trailing comma.\n        if (this.lexer.peek().type === TokenType.RBrace) break;\n        continue;\n      }\n      if (sep.type === TokenType.RBrace) break;\n      throw new FunctionInputError(\n        `jsmql could not parse the destructure pattern \u2014 expected ',' or '}' at position ${sep.pos}, got '${sep.value}'.`,\n        sep.pos,\n      );\n    }\n    this.lexer.next(); // consume `}`\n\n    if (opsKeys.length > 0 && paramBindings.length > 0) {\n      throw new FunctionInputError(\n        \"jsmql expects the operator-hint destructure (e.g. `{ $match, $project }`) to be separate from the params destructure (e.g. `{ minAge }`). \" +\n          \"Split into two parameters: `(params, $, opsHint) => \u2026`.\",\n        openBrace.pos,\n      );\n    }\n    if (paramBindings.length > 0) return { kind: \"params\", bindings: paramBindings, pos: openBrace.pos };\n    return { kind: \"ops\", pos: openBrace.pos };\n  }\n\n  /**\n   * Parse the body of a block-body arrow: `{ stmt (; stmt)* ;? }`. This is\n   * structurally the same as the top-level `;`-separated pipeline form\n   * (see `parse()`), terminated by `}` instead of EOF. A single-statement\n   * block body without `;` returns the underlying `Expr`/`UpdateFilter`\n   * unchanged; any `;` (including a trailing one) wraps as a `Pipeline`.\n   *\n   * `return` is rejected up front with a precise `FunctionInputError` so the\n   * user gets a clear pointer to either the `;`-separated form or an\n   * expression-body arrow, instead of the parser's generic \"unknown\n   * identifier\" message.\n   */\n  private parseBlockBody(): Program {\n    const openBrace = this.lexer.next(); // consume `{`\n\n    if (this.lexer.peek().type === TokenType.RBrace) {\n      throw new FunctionInputError(\"jsmql expects at least one statement inside a block-body arrow.\", openBrace.pos);\n    }\n\n    this.rejectReturn();\n    const stmts: PipelineStmt[] = [this.collectStatement()];\n    let sawSemi = false;\n    while (this.lexer.peek().type === TokenType.Semi) {\n      this.lexer.next();\n      sawSemi = true;\n      if (this.lexer.peek().type === TokenType.RBrace) break;\n      this.rejectReturn();\n      stmts.push(this.collectStatement());\n    }\n\n    const closeTok = this.lexer.peek();\n    if (closeTok.type !== TokenType.RBrace) {\n      throw new ParseError(`Expected '}' to close the block body at position ${closeTok.pos}`, closeTok.pos);\n    }\n    this.lexer.next();\n\n    const eof = this.lexer.peek();\n    if (eof.type !== TokenType.EOF) {\n      throw new ParseError(`Unexpected token after function body at position ${eof.pos}`, eof.pos);\n    }\n\n    if (!sawSemi) {\n      const only = stmts[0];\n      if (only.type === \"LetDecl\") this.throwLetOutsidePipeline(only.name, only.pos);\n      return only;\n    }\n    return { type: \"Pipeline\", stmts, pos: stmts[0].pos };\n  }\n\n  /**\n   * Parse the body of an expression-body arrow: a single jsmql statement,\n   * with one optional trailing `;` consumed as a formatter artifact. The\n   * trailing `;` does NOT trigger pipeline mode here \u2014 single-statement\n   * expression bodies preserve their object-shaped output, matching the\n   * documented contract for `jsmql(($) => \u2026)`.\n   */\n  private parseExpressionBody(): Program {\n    const stmt = this.collectStatement();\n    if (this.lexer.peek().type === TokenType.Semi) {\n      this.lexer.next();\n    }\n    const eof = this.lexer.peek();\n    if (eof.type !== TokenType.EOF) {\n      throw new ParseError(`Unexpected token after function body at position ${eof.pos}`, eof.pos);\n    }\n    if (stmt.type === \"LetDecl\") this.throwLetOutsidePipeline(stmt.name, stmt.pos);\n    return stmt;\n  }\n\n  /**\n   * Raised when a `let` declaration appears at the top of an input that turns\n   * out to be expression-mode (no `;` separator, not a bracketed pipeline).\n   * `let` only makes sense as a pipeline statement \u2014 there's no enclosing\n   * scope for the binding to live in otherwise.\n   */\n  private throwLetOutsidePipeline(name: string, pos: number): never {\n    throw new ParseError(\n      `\\`let ${name} = \u2026\\` is only valid inside a pipeline. ` +\n        `Add at least one more statement separated by \\`;\\` to flip into pipeline mode ` +\n        `(e.g. \\`let ${name} = \u2026; { $project: \u2026 }\\`). ` +\n        `The bracketed pipeline form \\`[ let ${name} = \u2026, \u2026 ]\\` works too.`,\n      pos,\n    );\n  }\n\n  /**\n   * Throw a precise `FunctionInputError` if the next token is the bare\n   * identifier `return`. Called at every statement-start position inside\n   * a block body, so a `return` token *inside* a string or expression\n   * (where it would just be a property name like `obj.return`) doesn't\n   * false-fire \u2014 only true statement-leading `return`s reach this check.\n   */\n  private rejectReturn(): void {\n    const tok = this.lexer.peek();\n    if (tok.type === TokenType.Ident && tok.value === \"return\") {\n      throw new FunctionInputError(\n        \"jsmql block-body arrows are a sequence of jsmql statements, not JavaScript control flow. \" +\n          \"Remove `return` \u2014 write the body as `;`-separated jsmql statements, or switch to an \" +\n          \"expression-body arrow `($) => EXPR`.\",\n        tok.pos,\n      );\n    }\n  }\n\n  /**\n   * Parse one top-level statement: either an expression or a update op chain\n   * (one or more comma-separated update ops sharing a stage). Stops at the\n   * first `;` or EOF; the caller (`parse()`) handles the `;` boundary.\n   */\n  private collectStatement(): PipelineStmt {\n    const first = this.lexer.peek();\n\n    // `let <ident> = <expr>` \u2014 pipeline-scoped local binding. Only legal in a\n    // pipeline context; codegen errors if it shows up in expression-mode input\n    // (no `;` boundary and not inside a bracketed pipeline).\n    if (first.type === TokenType.Let) {\n      return this.parseLetDecl();\n    }\n\n    // Tokens that can ONLY start a update op program: `delete`, `++`, `--`.\n    // Their presence at the start of a statement unambiguously commits us\n    // to update op parsing. Other update op forms (=, +=, x++, \u2026) reveal\n    // themselves only after a target expression has been parsed \u2014 below.\n    if (first.type === TokenType.Delete || first.type === TokenType.PlusPlus || first.type === TokenType.MinusMinus) {\n      return this.parseUpdateFilter();\n    }\n\n    // Speculative: parse a single expression first.\n    const expr = this.parseExpression();\n\n    // If an assignment operator follows, the expression we just parsed was\n    // actually a update op target \u2014 treat the rest of the statement as a\n    // update op chain.\n    if (this.peekAssignOp() !== null) {\n      this.validateUpdateTarget(expr);\n      return this.parseUpdateFilterFrom(expr);\n    }\n\n    // Postfix `x++` / `x--`.\n    if (this.peekIncDecOp() !== null) {\n      this.validateUpdateTarget(expr);\n      return this.parseUpdateFilterFromPostfix(expr);\n    }\n\n    // `parseExpression` may have surfaced an `AssignExpr` from a parenthesized\n    // top-level assignment (`($.a = 5)`). Wrap it in a UpdateFilter so\n    // codegen routes through the update op path.\n    if ((expr as unknown as { type: string }).type === \"AssignExpr\") {\n      const ops: UpdateOp[] = [expr as unknown as AssignExpr];\n      this.parseUpdateFilterRest(ops);\n      return { type: \"UpdateFilter\", ops, pos: ops[0].pos };\n    }\n\n    return expr;\n  }\n\n  // \u2500\u2500 Let declaration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n  /**\n   * Parse `let <ident> = <expr>`. The leading `let` token must already be the\n   * current peek; this consumes it and the rest of the declaration. The cursor\n   * is left at whatever follows the value expression (typically `;` or `,` in\n   * the array-pipeline form). No re-declaration check here \u2014 that needs a\n   * pipeline-level view and lives in codegen.\n   */\n  private parseLetDecl(): LetDecl {\n    const letTok = this.lexer.next(); // consume `let`\n    const ident = this.lexer.peek();\n    if (ident.type !== TokenType.Ident) {\n      throw new ParseError(\n        `Expected an identifier after \\`let\\` at position ${ident.pos}, got '${ident.value}'`,\n        ident.pos,\n      );\n    }\n    this.lexer.next(); // consume the identifier\n    const eq = this.lexer.peek();\n    if (eq.type !== TokenType.Eq) {\n      throw new ParseError(\n        `Expected '=' after \\`let ${ident.value}\\` at position ${eq.pos}, got '${eq.value}'. ` +\n          `\\`let\\` requires an initialiser \u2014 write \\`let ${ident.value} = <expr>\\`.`,\n        eq.pos,\n      );\n    }\n    this.lexer.next(); // consume `=`\n    const value = this.parseExpression();\n    return { type: \"LetDecl\", name: ident.value, value, pos: letTok.pos };\n  }\n\n  // \u2500\u2500 UpdateOp program \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n  /** Entry when the input starts with a update op token (`delete`). */\n  private parseUpdateFilter(): UpdateFilter {\n    const ops: UpdateOp[] = [];\n    ops.push(...this.parseUpdateOp());\n    this.parseUpdateFilterRest(ops);\n    return { type: \"UpdateFilter\", ops, pos: ops[0].pos };\n  }\n\n  /** Entry when the first target was already parsed as an expression. */\n  private parseUpdateFilterFrom(firstTarget: Expr): UpdateFilter {\n    const ops: UpdateOp[] = [];\n    ops.push(...this.parseAssignmentChainFrom(firstTarget));\n    this.parseUpdateFilterRest(ops);\n    return { type: \"UpdateFilter\", ops, pos: ops[0].pos };\n  }\n\n  /**\n   * Entry when the first target was parsed and is followed by `++` or `--`\n   * (postfix inc/dec). Validation must already have happened.\n   */\n  private parseUpdateFilterFromPostfix(firstTarget: Expr): UpdateFilter {\n    const op = this.peekIncDecOp();\n    if (op === null) {\n      const tok = this.lexer.peek();\n      throw new ParseError(`Expected '++' or '--' at position ${tok.pos}`, tok.pos);\n    }\n    this.lexer.next(); // consume the operator\n    const ops: UpdateOp[] = [this.makeIncDecUpdateOp(firstTarget, op)];\n    this.parseUpdateFilterRest(ops);\n    return { type: \"UpdateFilter\", ops, pos: ops[0].pos };\n  }\n\n  /**\n   * After the first update op is parsed, consume any `,`-separated tail.\n   * Stops at the first non-`,` token (typically `;` or EOF) and leaves\n   * the cursor there for the caller to handle.\n   */\n  private parseUpdateFilterRest(ops: UpdateOp[]): void {\n    while (this.peekUpdateOpSeparator()) {\n      this.lexer.next(); // consume `,`\n      const next = this.lexer.peek().type;\n      if (next === TokenType.EOF || next === TokenType.Semi) break; // trailing separator\n      ops.push(...this.parseUpdateOp());\n    }\n  }\n\n  /**\n   * Parse a single update op. Returns an array because a chained assignment\n   * (`$.a = $.b = expr`) flattens to multiple `AssignExpr` nodes here, all\n   * sharing the deepest RHS.\n   */\n  private parseUpdateOp(): UpdateOp[] {\n    if (this.lexer.peek().type === TokenType.Delete) {\n      return [this.parseDeleteStmt()];\n    }\n    // Prefix increment/decrement: `++$.x` / `--$.x`.\n    if (this.peekIncDecOp() !== null) {\n      return [this.parsePrefixIncDec()];\n    }\n    const target = this.parsePostfix();\n    // `parsePostfix` may have already returned a fully-formed update op when the\n    // input was wrapped in parens \u2014 `($.a = 1)` / `($.a++)`. Prettier and oxfmt\n    // emit this shape when a top-level assignment chains with `,`. Surface it\n    // as-is so a chain like `($.a = 1), ($.b = 2)` round-trips.\n    if ((target as unknown as { type: string }).type === \"AssignExpr\") {\n      return [target as unknown as AssignExpr];\n    }\n    this.validateUpdateTarget(target);\n    // Postfix increment/decrement: `$.x++` / `$.x--`.\n    const postfix = this.peekIncDecOp();\n    if (postfix !== null) {\n      this.lexer.next();\n      return [this.makeIncDecUpdateOp(target, postfix)];\n    }\n    return this.parseAssignmentChainFrom(target);\n  }\n\n  private parseDeleteStmt(): DeleteStmt {\n    const delTok = this.lexer.next(); // consume `delete`\n    const target = this.parsePostfix();\n    this.validateUpdateTarget(target);\n    return { type: \"DeleteStmt\", target, pos: delTok.pos };\n  }\n\n  /**\n   * Given a target already parsed and validated, expect an assignment operator\n   * and parse the RHS. Handles right-associative chains for `=`; rejects them\n   * for compound operators because `a += b += 1` is too easy to misread.\n   */\n  private parseAssignmentChainFrom(target: Expr): AssignExpr[] {\n    const opTok = this.lexer.peek();\n    const op = this.peekAssignOp();\n    if (op === null) {\n      throw new ParseError(`Expected assignment operator at position ${opTok.pos}`, opTok.pos);\n    }\n    this.lexer.next(); // consume the assignment op\n\n    if (op === \"=\") {\n      // Try to peek a chained target: `<target> = <target> = \u2026`. The peek-ahead\n      // is bounded (DollarDot, Ident segments, dots) so this is cheap.\n      if (this.peekIsAssignmentChainStart()) {\n        const subTarget = this.parsePostfix();\n        this.validateUpdateTarget(subTarget);\n        const sub = this.parseAssignmentChainFrom(subTarget);\n        const deepestValue = sub[sub.length - 1].value;\n        return [{ type: \"AssignExpr\", target, value: deepestValue, pos: target.pos }, ...sub];\n      }\n      const value = this.parseExpression();\n      return [{ type: \"AssignExpr\", target, value, pos: target.pos }];\n    }\n\n    // Compound op (+=, -=, *=, /=). Reject chained.\n    if (this.peekIsAssignmentChainStart()) {\n      const tok = this.lexer.peek();\n      throw new ParseError(\n        `Compound assignment cannot be chained at position ${tok.pos} \u2014 split into separate statements`,\n        tok.pos,\n      );\n    }\n    const rhs = this.parseExpression();\n    const desugared: Expr = { type: \"BinaryExpr\", op: compoundBinaryOp(op), left: target, right: rhs, pos: target.pos };\n    return [{ type: \"AssignExpr\", target, value: desugared, pos: target.pos }];\n  }\n\n  /**\n   * Returns the assignment operator string at the current position, or null\n   * if the next token is not an assignment operator.\n   */\n  private peekAssignOp(): \"=\" | \"+=\" | \"-=\" | \"*=\" | \"/=\" | null {\n    switch (this.lexer.peek().type) {\n      case TokenType.Eq:\n        return \"=\";\n      case TokenType.PlusEq:\n        return \"+=\";\n      case TokenType.MinusEq:\n        return \"-=\";\n      case TokenType.StarEq:\n        return \"*=\";\n      case TokenType.SlashEq:\n        return \"/=\";\n      default:\n        return null;\n    }\n  }\n\n  private isAssignOpType(t: TokenType): boolean {\n    return (\n      t === TokenType.Eq ||\n      t === TokenType.PlusEq ||\n      t === TokenType.MinusEq ||\n      t === TokenType.StarEq ||\n      t === TokenType.SlashEq\n    );\n  }\n\n  private peekUpdateOpSeparator(): boolean {\n    return this.lexer.peek().type === TokenType.Comma;\n  }\n\n  /**\n   * Returns \"++\" or \"--\" if the next token is an inc/dec operator, else null.\n   * Used at both prefix (start of update op) and postfix (after a target)\n   * positions; the caller decides which.\n   */\n  private peekIncDecOp(): \"++\" | \"--\" | null {\n    switch (this.lexer.peek().type) {\n      case TokenType.PlusPlus:\n        return \"++\";\n      case TokenType.MinusMinus:\n        return \"--\";\n      default:\n        return null;\n    }\n  }\n\n  /**\n   * Parse a prefix `++<target>` or `--<target>`. The prefix vs postfix\n   * distinction is irrelevant in MQL pipeline context \u2014 both forms compile\n   * to the same `$set: { x: { $add|$subtract: [\"$x\", 1] } }` shape, since\n   * pipeline stages don't carry \"value of expression\" semantics.\n   */\n  private parsePrefixIncDec(): AssignExpr {\n    const op = this.peekIncDecOp();\n    if (op === null) {\n      const tok = this.lexer.peek();\n      throw new ParseError(`Expected '++' or '--' at position ${tok.pos}`, tok.pos);\n    }\n    this.lexer.next(); // consume `++` or `--`\n    const target = this.parsePostfix();\n    this.validateUpdateTarget(target);\n    return this.makeIncDecUpdateOp(target, op);\n  }\n\n  /** Build the desugared AssignExpr for `target++` / `target--` / `++target` / `--target`. */\n  private makeIncDecUpdateOp(target: Expr, op: \"++\" | \"--\"): AssignExpr {\n    const value: Expr = {\n      type: \"BinaryExpr\",\n      op: op === \"++\" ? \"+\" : \"-\",\n      left: target,\n      right: { type: \"NumberLiteral\", value: 1, pos: target.pos },\n      pos: target.pos,\n    };\n    return { type: \"AssignExpr\", target, value, pos: target.pos };\n  }\n\n  /**\n   * Lookahead: do the next tokens look like `$.path[.path]* <assignOp>`?\n   * Used to detect the start of a chained assignment's RHS when we're at\n   * the right of a `=` operator. Bounded by the length of the field path\n   * so it's cheap and never false-positive on regular RHS expressions.\n   */\n  private peekIsAssignmentChainStart(): boolean {\n    if (this.lexer.peek().type !== TokenType.DollarDot) return false;\n    let offset = 1;\n    if (!this.isIdentOrKeyword(this.lexer.lookahead(offset))) return false;\n    offset++;\n    while (this.lexer.lookahead(offset).type === TokenType.Dot) {\n      offset++;\n      if (!this.isIdentOrKeyword(this.lexer.lookahead(offset))) return false;\n      offset++;\n    }\n    return this.isAssignOpType(this.lexer.lookahead(offset).type);\n  }\n\n  /**\n   * UpdateOp targets are restricted to field paths: a `FieldRef` (`$.x`) or\n   * a chain of `MemberAccess` nodes rooted at one (`$.x.y.z`). Anything else\n   * \u2014 index access, function calls, parameter refs, parenthesized expressions\n   * containing operators \u2014 is rejected with a precise error.\n   */\n  private validateUpdateTarget(target: Expr): void {\n    if (this.isFieldPathTarget(target)) return;\n    // `$out` sugar: `$$$.<coll> = \u2026`, `$$$$.<db>.<coll> = \u2026`, and their bracket\n    // variants. Shape-only check here \u2014 segment-count, computed-bracket, and\n    // any other malformations are diagnosed at codegen time in\n    // `detectOutAssign` (src/out-translation.ts) so the error message can\n    // suggest the right corrective form.\n    if (this.isOutTarget(target)) return;\n    const pos = this.lexer.peek().pos;\n    if (target.type === \"ParamRef\") {\n      throw new ParseError(\n        `UpdateOp target must be a field path like '$.${target.name}', not a bare identifier (at position ${pos})`,\n        pos,\n      );\n    }\n    if (target.type === \"IndexAccess\") {\n      throw new ParseError(\n        `UpdateOp target must be a static field path; computed/index access ('[\u2026]') is not supported (at position ${pos})`,\n        pos,\n      );\n    }\n    throw new ParseError(\n      `Cannot assign to ${describeUpdateTarget(target)} at position ${pos} \u2014 only field paths like '$.x' or '$.x.y' are assignable.`,\n      pos,\n    );\n  }\n\n  private isFieldPathTarget(target: Expr): boolean {\n    if (target.type === \"FieldRef\") return true;\n    // Bare `$$` is a valid assignment target for the stream-level\n    // root-replacement form (`$$ = <expr>`). The parser accepts the shape\n    // here; pipeline lowering enforces the supported RHS forms.\n    if (target.type === \"CollectionRef\") return true;\n    if (target.type === \"MemberAccess\") return this.isFieldPathTarget(target.object);\n    return false;\n  }\n\n  /**\n   * Accept the `$out` sugar LHS shape: one or two static (dot or bracket)\n   * accesses rooted at `DatabaseRef` (`$$$`) or `ClusterRef` (`$$$$`). The\n   * detailed validation (right segment count, no computed bracket) lives in\n   * codegen \u2014 at parse time we only commit to \"this looks like a write\n   * destination\" so the assignment can be built and routed.\n   */\n  private isOutTarget(target: Expr): boolean {\n    if (target.type === \"DatabaseRef\" || target.type === \"ClusterRef\") return true;\n    if (target.type === \"MemberAccess\") return this.isOutTarget(target.object);\n    if (target.type === \"IndexAccess\") return this.isOutTarget(target.object);\n    return false;\n  }\n\n  // \u2500\u2500 Precedence hierarchy (low \u2192 high) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n  private parseExpression(): Expr {\n    if (++this.depth > MAX_RECURSION_DEPTH) {\n      this.depth--;\n      const pos = this.lexer.peek().pos;\n      throw new ParseError(`Expression nests too deeply (max ${MAX_RECURSION_DEPTH} levels) at position ${pos}`, pos);\n    }\n    try {\n      return this.parseTernary();\n    } finally {\n      this.depth--;\n    }\n  }\n\n  /** ternary:  nullish (\"?\" expression \":\" ternary)?  \u2014 right-associative */\n  private parseTernary(): Expr {\n    const condition = this.parseNullish();\n    if (this.lexer.peek().type !== TokenType.Quest) return condition;\n    this.lexer.next(); // consume ?\n    const consequent = this.parseExpression(); // full expr for consequent\n    const colon = this.lexer.peek();\n    if (colon.type !== TokenType.Colon) {\n      throw new ParseError(`Expected ':' in ternary expression at position ${colon.pos}`, colon.pos);\n    }\n    this.lexer.next(); // consume :\n    const alternate = this.parseTernary(); // right-associative\n    return { type: \"TernaryExpr\", condition, consequent, alternate, pos: condition.pos };\n  }\n\n  /** nullish:  or (\"??\" or)*  \u2014 left-associative, flattened later */\n  private parseNullish(): Expr {\n    let left = this.parseOr();\n    while (this.lexer.peek().type === TokenType.QuestQuest) {\n      this.lexer.next();\n      const right = this.parseOr();\n      left = { type: \"BinaryExpr\", op: \"??\", left, right, pos: left.pos };\n    }\n    return left;\n  }\n\n  /** or:  and (\"||\" and)*  */\n  private parseOr(): Expr {\n    let left = this.parseAnd();\n    while (this.lexer.peek().type === TokenType.PipePipe) {\n      this.lexer.next();\n      const right = this.parseAnd();\n      left = { type: \"BinaryExpr\", op: \"||\", left, right, pos: left.pos };\n    }\n    return left;\n  }\n\n  /** and:  bitOr (\"&&\" bitOr)*  */\n  private parseAnd(): Expr {\n    let left = this.parseBitOr();\n    while (this.lexer.peek().type === TokenType.AmpAmp) {\n      this.lexer.next();\n      const right = this.parseBitOr();\n      left = { type: \"BinaryExpr\", op: \"&&\", left, right, pos: left.pos };\n    }\n    return left;\n  }\n\n  /** bitOr:  bitXor (\"|\" bitXor)*  */\n  private parseBitOr(): Expr {\n    let left = this.parseBitXor();\n    while (this.lexer.peek().type === TokenType.Pipe) {\n      this.lexer.next();\n      const right = this.parseBitXor();\n      left = { type: \"BinaryExpr\", op: \"|\", left, right, pos: left.pos };\n    }\n    return left;\n  }\n\n  /** bitXor:  bitAnd (\"^\" bitAnd)*  */\n  private parseBitXor(): Expr {\n    let left = this.parseBitAnd();\n    while (this.lexer.peek().type === TokenType.Caret) {\n      this.lexer.next();\n      const right = this.parseBitAnd();\n      left = { type: \"BinaryExpr\", op: \"^\", left, right, pos: left.pos };\n    }\n    return left;\n  }\n\n  /** bitAnd:  comparison (\"&\" comparison)*  */\n  private parseBitAnd(): Expr {\n    let left = this.parseComparison();\n    while (this.lexer.peek().type === TokenType.Amp) {\n      this.lexer.next();\n      const right = this.parseComparison();\n      left = { type: \"BinaryExpr\", op: \"&\", left, right, pos: left.pos };\n    }\n    return left;\n  }\n\n  /**\n   * comparison:  relational [ (==|!=|===|!==) relational ]\n   * Non-chainable. Lower precedence than relational (<, <=, >, >=, in) to match JS.\n   */\n  private parseComparison(): Expr {\n    const left = this.parseRelational();\n    const op = this.peekEqualityOp();\n    if (!op) return left;\n    this.lexer.next();\n    const right = this.parseRelational();\n    return { type: \"BinaryExpr\", op, left, right, pos: left.pos };\n  }\n\n  private peekEqualityOp(): BinaryOp | null {\n    switch (this.lexer.peek().type) {\n      case TokenType.EqEq:\n        return \"==\";\n      case TokenType.EqEqEq:\n        return \"===\";\n      case TokenType.BangEq:\n        return \"!=\";\n      case TokenType.BangEqEq:\n        return \"!==\";\n      default:\n        return null;\n    }\n  }\n\n  /**\n   * relational:  additive [ (<|<=|>|>=|in) additive ]\n   * Non-chainable. Higher precedence than equality to match JS.\n   */\n  private parseRelational(): Expr {\n    const left = this.parseAdditive();\n    const op = this.peekRelationalOp();\n    if (!op) return left;\n    this.lexer.next();\n    const right = this.parseAdditive();\n    return { type: \"BinaryExpr\", op, left, right, pos: left.pos };\n  }\n\n  private peekRelationalOp(): BinaryOp | null {\n    switch (this.lexer.peek().type) {\n      case TokenType.Gt:\n        return \">\";\n      case TokenType.GtEq:\n        return \">=\";\n      case TokenType.Lt:\n        return \"<\";\n      case TokenType.LtEq:\n        return \"<=\";\n      case TokenType.In:\n        return \"in\";\n      default:\n        return null;\n    }\n  }\n\n  /** additive:  multiplicative ((+|-) multiplicative)*  */\n  private parseAdditive(): Expr {\n    let left = this.parseMultiplicative();\n    while (this.lexer.peek().type === TokenType.Plus || this.lexer.peek().type === TokenType.Minus) {\n      const op: BinaryOp = this.lexer.next().type === TokenType.Plus ? \"+\" : \"-\";\n      const right = this.parseMultiplicative();\n      left = { type: \"BinaryExpr\", op, left, right, pos: left.pos };\n    }\n    return left;\n  }\n\n  /** multiplicative:  power ((*|/|%) power)*  */\n  private parseMultiplicative(): Expr {\n    let left = this.parsePower();\n    for (;;) {\n      const t = this.lexer.peek().type;\n      let op: BinaryOp | null = null;\n      if (t === TokenType.Star) op = \"*\";\n      else if (t === TokenType.Slash) op = \"/\";\n      else if (t === TokenType.Percent) op = \"%\";\n      if (!op) break;\n      this.lexer.next();\n      const right = this.parsePower();\n      left = { type: \"BinaryExpr\", op, left, right, pos: left.pos };\n    }\n    return left;\n  }\n\n  /** power:  unary (\"**\" power)?  \u2014 right-associative  */\n  private parsePower(): Expr {\n    const left = this.parseUnary();\n    if (this.lexer.peek().type !== TokenType.StarStar) return left;\n    this.lexer.next();\n    const right = this.parsePower(); // right-associative\n    return { type: \"BinaryExpr\", op: \"**\", left, right, pos: left.pos };\n  }\n\n  /** unary:  typeof | (\"!\"|\"-\"|\"~\") unary  |  postfix  */\n  private parseUnary(): Expr {\n    const t = this.lexer.peek();\n    if (t.type === TokenType.Typeof) {\n      this.lexer.next();\n      const operand = this.parseUnary();\n      return { type: \"TypeofExpr\", operand, pos: t.pos };\n    }\n    if (t.type === TokenType.Bang) {\n      this.lexer.next();\n      const operand = this.parseUnary();\n      return { type: \"UnaryExpr\", op: \"!\", operand, pos: t.pos };\n    }\n    if (t.type === TokenType.Minus) {\n      this.lexer.next();\n      const operand = this.parseUnary();\n      return { type: \"UnaryExpr\", op: \"-\", operand, pos: t.pos };\n    }\n    if (t.type === TokenType.Tilde) {\n      this.lexer.next();\n      const operand = this.parseUnary();\n      return { type: \"UnaryExpr\", op: \"~\", operand, pos: t.pos };\n    }\n    return this.parsePostfix();\n  }\n\n  /**\n   * postfix:  primary ( \"[\" expression \"]\" | \".\" member | \"?.\" member | \"?.[\" expression \"]\" )*\n   *\n   * Optional chaining (`?.`) produces the same AST node shape as the non-optional\n   * counterpart, but with `optional: true`. The codegen consults this flag at every\n   * null-unsafe consumer site (array spread, array/string method receivers, string\n   * `$concat`, template-literal interpolations, `.length`, `Object.keys`/etc.) to\n   * wrap the chain's result with `$ifNull(v, neutral)`, where `neutral` is `[]`\n   * / `\"\"` / `{}` depending on the consumer. See `chainHasOptional` /\n   * `wrapIfNull` in src/codegen.ts and docs/specs/method-dispatch.md.\n   */\n  private parsePostfix(): Expr {\n    let left = this.parsePrimary();\n    for (;;) {\n      const t = this.lexer.peek().type;\n      if (t === TokenType.LParen) {\n        // Direct call expression: e.g. ((x) => body)(arg) \u2014 only meaningful when the\n        // callee is a lambda (IIFE). Codegen emits $let; non-lambda callees error there.\n        const args = this.parseMethodCallArgs();\n        left = { type: \"CallExpression\", callee: left, args, pos: left.pos };\n        continue;\n      }\n      if (t === TokenType.LBracket) {\n        this.lexer.next(); // consume [\n        const index = this.parseExpression();\n        const close = this.lexer.peek();\n        if (close.type !== TokenType.RBracket) {\n          throw new ParseError(`Expected ']' after index expression at position ${close.pos}`, close.pos);\n        }\n        this.lexer.next(); // consume ]\n        left = { type: \"IndexAccess\", object: left, index, pos: left.pos };\n      } else if (t === TokenType.Dot || t === TokenType.QuestDot) {\n        const isOptional = t === TokenType.QuestDot;\n        this.lexer.next(); // consume . or ?.\n        // ?.[...] form \u2014 optional bracket access\n        if (isOptional && this.lexer.peek().type === TokenType.LBracket) {\n          this.lexer.next(); // consume [\n          const index = this.parseExpression();\n          const close = this.lexer.peek();\n          if (close.type !== TokenType.RBracket) {\n            throw new ParseError(`Expected ']' after index expression at position ${close.pos}`, close.pos);\n          }\n          this.lexer.next();\n          left = { type: \"IndexAccess\", object: left, index, pos: left.pos, optional: true };\n          continue;\n        }\n        const member = this.lexer.peek();\n        if (!this.isIdentOrKeyword(member)) {\n          throw new ParseError(`Expected property name after '.' at position ${member.pos}`, member.pos);\n        }\n        this.lexer.next(); // consume member name\n        if (this.lexer.peek().type === TokenType.LParen) {\n          // Method call: left.member(args). Block-body lambdas (a sub-pipeline\n          // body inside the predicate) are allowed for:\n          //   - `$$$.<coll>.find/.filter(...)` (rooted at DatabaseRef) \u2014 the\n          //     eventual `$lookup` stage's sub-pipeline body. See\n          //     docs/specs/lookup-stage.md.\n          //   - `$$.filter(...)` (rooted directly at CollectionRef) \u2014 the\n          //     facet entry's sub-pipeline body. See\n          //     docs/specs/replace-root-stage.md (#facet pattern).\n          const allowBlockBody =\n            ((member.value === \"find\" || member.value === \"filter\") && isLookupReceiverRooted(left)) ||\n            (member.value === \"filter\" && left.type === \"CollectionRef\");\n          const args = this.parseMethodCallArgs(allowBlockBody);\n          left = {\n            type: \"MethodCall\",\n            object: left,\n            method: member.value,\n            args,\n            pos: left.pos,\n            ...(isOptional && { optional: true }),\n          };\n        } else {\n          // Property access: left.member\n          left = {\n            type: \"MemberAccess\",\n            object: left,\n            member: member.value,\n            pos: left.pos,\n            ...(isOptional && { optional: true }),\n          };\n        }\n      } else {\n        break;\n      }\n    }\n    return left;\n  }\n\n  /** Parse method call argument list: \"(\" [argOrLambda (, argOrLambda)*] \")\" */\n  private parseMethodCallArgs(allowBlockBody: boolean = false): CallArg[] {\n    this.lexer.expect(TokenType.LParen);\n    if (this.lexer.peek().type === TokenType.RParen) {\n      this.lexer.next();\n      return [];\n    }\n    const args: CallArg[] = [this.parseCallArg(allowBlockBody)];\n    while (this.lexer.peek().type === TokenType.Comma) {\n      this.lexer.next();\n      args.push(this.parseCallArg(allowBlockBody));\n    }\n    this.lexer.expect(TokenType.RParen);\n    return args;\n  }\n\n  /**\n   * Parse one argument in a call site. Allows:\n   *   - ...expr (spread)\n   *   - lambda forms (x => ..., (x) => ..., (x, y) => ...)\n   *   - any expression\n   */\n  private parseCallArg(allowBlockBody: boolean = false): CallArg {\n    if (this.lexer.peek().type === TokenType.Spread) {\n      const spreadTok = this.lexer.next();\n      const argument = this.parseExpression();\n      const spread: SpreadElement = { type: \"SpreadElement\", argument, pos: spreadTok.pos };\n      return spread;\n    }\n    return this.parseArgOrLambda(allowBlockBody);\n  }\n\n  /**\n   * Parse an argument that might be a lambda expression.\n   * Checks for lambda patterns before falling back to parseExpression().\n   * When `allowBlockBody` is true, the lambda body may be a `{ stmt; stmt; }`\n   * block (only set inside `$$$.<coll>.find/filter(...)`); otherwise `=> {`\n   * keeps its current meaning (object-literal start via parseObjectLiteral).\n   */\n  private parseArgOrLambda(allowBlockBody: boolean = false): Expr {\n    // x => expr  (unparenthesized single param)\n    if (this.lexer.peek().type === TokenType.Ident && this.lexer.lookahead(1).type === TokenType.Arrow) {\n      return this.parseLambdaUnparen(allowBlockBody);\n    }\n    // (x) => expr  or  (x, y) => expr  or  () => expr\n    if (this.isLambdaStart()) {\n      return this.parseLambdaParen(allowBlockBody);\n    }\n    return this.parseExpression();\n  }\n\n  /** primary:  operator_call | field_ref | literals | \"(\" expr \")\" | array | object  */\n  private parsePrimary(): Expr {\n    const t = this.lexer.peek();\n\n    switch (t.type) {\n      case TokenType.Dollar:\n        // `$` followed by an identifier is an operator call (`$add(...)`).\n        // `$` standalone is the current document \u2014 same role MQL's `$$ROOT`\n        // plays. Used as a value (`{ ...$, x: 1 }`, `$mergeObjects($, ...)`)\n        // and as the LHS of `$ = <expr>` to replace the root document.\n        if (this.isIdentOrKeyword(this.lexer.lookahead(1))) return this.parseOperatorCall();\n        this.lexer.next();\n        return { type: \"FieldRef\", path: \"\", pos: t.pos };\n      case TokenType.DollarDot:\n        return this.parseFieldRef();\n      case TokenType.DoubleDollar:\n        return this.parseContextRef(\"CollectionRef\", \"$$\");\n      case TokenType.TripleDollar:\n        return this.parseContextRef(\"DatabaseRef\", \"$$$\");\n      case TokenType.QuadDollar:\n        return this.parseContextRef(\"ClusterRef\", \"$$$$\");\n      case TokenType.Number:\n        return this.parseNumber();\n      case TokenType.BigInt:\n        this.lexer.next();\n        return { type: \"BigIntLiteral\", value: t.value, pos: t.pos };\n      case TokenType.String:\n        this.lexer.next();\n        return { type: \"StringLiteral\", value: t.value, pos: t.pos };\n      case TokenType.True:\n        this.lexer.next();\n        return { type: \"BooleanLiteral\", value: true, pos: t.pos };\n      case TokenType.False:\n        this.lexer.next();\n        return { type: \"BooleanLiteral\", value: false, pos: t.pos };\n      case TokenType.Null:\n        this.lexer.next();\n        return { type: \"NullLiteral\", pos: t.pos };\n      case TokenType.Undefined:\n        this.lexer.next();\n        return { type: \"UndefinedLiteral\", pos: t.pos };\n      case TokenType.LBracket:\n        return this.parseArrayLiteral();\n      case TokenType.LBrace:\n        return this.parseObjectLiteral();\n      case TokenType.RegexLiteral:\n        this.lexer.next();\n        return { type: \"RegexLiteral\", pattern: t.value, flags: t.flags ?? \"\", pos: t.pos };\n      case TokenType.TemplateStart:\n        return this.parseTemplateLiteral();\n      case TokenType.New:\n        return this.parseNewDate();\n      case TokenType.LParen:\n        if (this.isLambdaStart()) return this.parseLambdaParen();\n        return this.parseGrouped();\n      case TokenType.Ident: {\n        const name = t.value;\n        if (name === \"Math\") return this.parseMathReference();\n        if (name === \"Object\") return this.parseObjectCall();\n        if (name === \"Date\" && this.lexer.lookahead(1).type === TokenType.Dot) {\n          return this.parseDateStatic();\n        }\n        if (name === \"Array\" && this.lexer.lookahead(1).type === TokenType.Dot) {\n          return this.parseArrayStaticCall();\n        }\n        if (name === \"Number\" && this.lexer.lookahead(1).type === TokenType.Dot) {\n          return this.parseNumberStaticCall();\n        }\n        if (TYPE_CAST_NAMES.has(name)) {\n          if (this.lexer.lookahead(1).type === TokenType.LParen) return this.parseTypeCast();\n          if (BARE_CAST_NAMES.has(name as BareCastOp)) {\n            this.lexer.next();\n            return { type: \"TypeCastRef\", cast: name as BareCastOp, pos: t.pos };\n          }\n          // parseInt / parseFloat without `(` falls through to parseTypeCast(),\n          // which throws the existing \"Expected LParen\" error.\n          return this.parseTypeCast();\n        }\n        this.lexer.next();\n        return { type: \"ParamRef\", name, pos: t.pos };\n      }\n      default:\n        if (t.type === TokenType.EOF) {\n          throw new ParseError(`Unexpected end of expression`, t.pos);\n        }\n        throw new ParseError(`Unexpected token '${t.value}' at position ${t.pos}`, t.pos);\n    }\n  }\n\n  // \u2500\u2500 Sub-parsers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n  /** \"(\" expression \")\"  \u2014 also handles `(x => expr)`, the unparen-single-param lambda */\n  private parseGrouped(): Expr {\n    this.lexer.expect(TokenType.LParen);\n    let expr: Expr;\n    if (this.lexer.peek().type === TokenType.Ident && this.lexer.lookahead(1).type === TokenType.Arrow) {\n      expr = this.parseLambdaUnparen();\n    } else if (this.peekIncDecOp() !== null) {\n      // Prefix `(++$.x)` / `(--$.x)` \u2014 parens around prefix inc/dec. Same\n      // formatter-friendly motivation as the assignment case below.\n      expr = this.parsePrefixIncDec() as unknown as Expr;\n    } else {\n      expr = this.parseExpression();\n      // `($.x = expr)` \u2014 parenthesized assignment. JS-syntax-equivalent to\n      // a bare `$.x = expr`; matters because formatters (oxfmt, prettier)\n      // wrap assignment expressions in parens when they appear in array\n      // element position. Parse the assignment here so the function-input\n      // form `jsmql(($) => [($.a = 1)])` works the same as the bare form.\n      // The result is an AssignExpr; we surface it as an `Expr` and let\n      // contextual handling in parseArrayLiteral / parse() / _generate\n      // route it appropriately. Plain expression contexts (e.g. `1 + (a=2)`)\n      // bubble it up to codegen which throws a precise error.\n      if (this.peekAssignOp() !== null) {\n        this.validateUpdateTarget(expr);\n        const chain = this.parseAssignmentChainFrom(expr);\n        if (chain.length !== 1) {\n          const tok = this.lexer.peek();\n          throw new ParseError(\n            `Chained assignment inside parentheses is not supported at position ${tok.pos}`,\n            tok.pos,\n          );\n        }\n        expr = chain[0] as unknown as Expr;\n      } else if (this.peekIncDecOp() !== null) {\n        // Postfix `($.x++)` / `($.x--)` \u2014 parens around postfix inc/dec.\n        const op = this.peekIncDecOp()!;\n        this.lexer.next();\n        this.validateUpdateTarget(expr);\n        expr = this.makeIncDecUpdateOp(expr, op) as unknown as Expr;\n      }\n    }\n    const close = this.lexer.peek();\n    if (close.type !== TokenType.RParen) {\n      throw new ParseError(`Expected ')' at position ${close.pos}`, close.pos);\n    }\n    this.lexer.next();\n    return expr;\n  }\n\n  private parseOperatorCall(): Expr {\n    const dollar = this.lexer.next(); // consume $\n    const nameTok = this.lexer.peek();\n    if (!this.isIdentOrKeyword(nameTok)) {\n      throw new ParseError(`Expected operator name after '$' at position ${dollar.pos}`, dollar.pos);\n    }\n    this.lexer.next();\n    const name = `$${nameTok.value}`;\n\n    this.lexer.expect(TokenType.LParen);\n\n    const peek = this.lexer.peek();\n\n    // Zero-arg call\n    if (peek.type === TokenType.RParen) {\n      this.lexer.next();\n      return { type: \"OperatorCall\", name, style: \"positional\", args: [], pos: dollar.pos };\n    }\n\n    // Object-style: single `{...}` arg with no trailing comma\n    if (peek.type === TokenType.LBrace) {\n      const obj = this.parseObjectLiteral();\n      const after = this.lexer.peek();\n      if (after.type === TokenType.RParen) {\n        this.lexer.next();\n        return { type: \"OperatorCall\", name, style: \"object\", args: [obj], pos: dollar.pos };\n      }\n      // First positional arg happens to be an object \u2014 collect remaining args\n      const args: CallArg[] = [obj];\n      while (this.lexer.peek().type === TokenType.Comma) {\n        this.lexer.next();\n        args.push(this.parseCallArg());\n      }\n      this.lexer.expect(TokenType.RParen);\n      return { type: \"OperatorCall\", name, style: \"positional\", args, pos: dollar.pos };\n    }\n\n    // Positional args (may include lambdas and spreads)\n    const args: CallArg[] = [this.parseCallArg()];\n    while (this.lexer.peek().type === TokenType.Comma) {\n      this.lexer.next();\n      args.push(this.parseCallArg());\n    }\n    this.lexer.expect(TokenType.RParen);\n    return { type: \"OperatorCall\", name, style: \"positional\", args, pos: dollar.pos };\n  }\n\n  /** $.field \u2014 stops at first segment; postfix handles further dots */\n  private parseFieldRef(): Expr {\n    const dollarDot = this.lexer.next(); // consume $.\n    const first = this.lexer.peek();\n    if (!this.isIdentOrKeyword(first)) {\n      throw new ParseError(`Expected field name after '$.' at position ${dollarDot.pos}`, dollarDot.pos);\n    }\n    this.lexer.next();\n    return { type: \"FieldRef\", path: first.value, pos: dollarDot.pos };\n  }\n\n  /**\n   * Context-reference prefix: `$$` (collection), `$$$` (database), `$$$$` (cluster).\n   * Returns a bare marker AST node; postfix `.name` (MemberAccess) and `[expr]`\n   * (IndexAccess) compose via the standard primary-postfix loop.\n   *\n   * Sanity-guards that the next token is `.` or `[` so bare `$$$` / `$$$$`\n   * (which are meaningless on their own) produce an actionable error rather\n   * than a downstream surprise. `$$` (CollectionRef) is more permissive: it\n   * is valid as the LHS of `$$ = <expr>` (the stream-level replacement) and\n   * as the RHS of `$$$.coll = $$` (the no-op `$out` write of the current\n   * stream), so for CollectionRef we accept anything that isn't an\n   * identifier-like follower. The typo case `$$foo` (no separator, an Ident\n   * next) is still rejected so the user sees the actionable\n   * \"Expected '.<name>' or '[<expr>]'\" hint; codegen continues to gate bare\n   * `$$` in unsupported positions via the CollectionRef branch.\n   */\n  private parseContextRef(nodeType: \"CollectionRef\" | \"DatabaseRef\" | \"ClusterRef\", displayPrefix: string): Expr {\n    const prefix = this.lexer.next();\n    const next = this.lexer.peek();\n    if (next.type !== TokenType.Dot && next.type !== TokenType.LBracket) {\n      if (nodeType === \"CollectionRef\" && !this.isIdentOrKeyword(next)) {\n        return { type: nodeType, pos: prefix.pos };\n      }\n      throw new ParseError(\n        `Expected '.<name>' or '[<expr>]' after '${displayPrefix}' at position ${prefix.pos}`,\n        prefix.pos,\n      );\n    }\n    return { type: nodeType, pos: prefix.pos };\n  }\n\n  /**\n   * An identifier-like token \u2014 a regular `Ident` or one of the reserved-word\n   * keywords (`in`, `new`, `typeof`) we accept in identifier position. Valid\n   * after `.` (field-path segments, member names), after `$` (operator names),\n   * and as a `$<key>` in object literals.\n   */\n  private isIdentOrKeyword(t: Token): boolean {\n    return (\n      t.type === TokenType.Ident ||\n      t.type === TokenType.In ||\n      t.type === TokenType.New ||\n      t.type === TokenType.Typeof ||\n      t.type === TokenType.Let\n    );\n  }\n\n  /**\n   * Non-consuming lookahead: is the current position the start of a parenthesized lambda?\n   * Matches: \"(\" \")\" \"=>\" | \"(\" Ident \")\" \"=>\" | \"(\" Ident (\",\" Ident)* \")\" \"=>\"\n   */\n  private isLambdaStart(): boolean {\n    if (this.lexer.peek().type !== TokenType.LParen) return false;\n    let offset = 1;\n    // Check for () => (zero params)\n    if (this.lexer.lookahead(offset).type === TokenType.RParen) {\n      return this.lexer.lookahead(offset + 1).type === TokenType.Arrow;\n    }\n    // Collect Ident (, Ident)*\n    while (this.lexer.lookahead(offset).type === TokenType.Ident) {\n      offset++;\n      if (this.lexer.lookahead(offset).type === TokenType.RParen) {\n        return this.lexer.lookahead(offset + 1).type === TokenType.Arrow;\n      }\n      if (this.lexer.lookahead(offset).type !== TokenType.Comma) return false;\n      offset++; // consume comma\n    }\n    return false;\n  }\n\n  /** Parse \"x => expr\" \u2014 single unparenthesized parameter */\n  private parseLambdaUnparen(allowBlockBody: boolean = false): Expr {\n    const paramTok = this.lexer.next(); // consume Ident\n    this.lexer.next(); // consume =>\n    if (allowBlockBody && this.lexer.peek().type === TokenType.LBrace) {\n      const block = this.parseLambdaBlockBody();\n      return { type: \"Lambda\", params: [paramTok.value], block, pos: paramTok.pos };\n    }\n    const body = this.parseExpression();\n    return { type: \"Lambda\", params: [paramTok.value], body, pos: paramTok.pos };\n  }\n\n  /** Parse \"(x) => expr\" or \"(x, y) => expr\" or \"() => expr\" */\n  private parseLambdaParen(allowBlockBody: boolean = false): Expr {\n    const lparen = this.lexer.next(); // consume (\n    const params: string[] = [];\n    if (this.lexer.peek().type !== TokenType.RParen) {\n      params.push(this.lexer.expect(TokenType.Ident).value);\n      while (this.lexer.peek().type === TokenType.Comma) {\n        this.lexer.next();\n        params.push(this.lexer.expect(TokenType.Ident).value);\n      }\n    }\n    this.lexer.expect(TokenType.RParen);\n    this.lexer.expect(TokenType.Arrow);\n    if (allowBlockBody && this.lexer.peek().type === TokenType.LBrace) {\n      const block = this.parseLambdaBlockBody();\n      return { type: \"Lambda\", params, block, pos: lparen.pos };\n    }\n    const body = this.parseExpression();\n    return { type: \"Lambda\", params, body, pos: lparen.pos };\n  }\n\n  /**\n   * Parse the block-body of a lookup-callback lambda: `{ stmt; stmt; }`.\n   * The block reuses the same machinery as the top-level `;`-separated\n   * pipeline form \u2014 every statement must be a stage call, an update op\n   * (`$.x = \u2026`, `delete $.x`), or a `let` binding. The result is normalised\n   * to a `Pipeline` (one stmt = single-stage pipeline, several = multi-stage).\n   * Only callable when the lookup-callback `allowBlockBody` flag is set \u2014\n   * outside that, `=> {` keeps its existing object-literal interpretation.\n   */\n  private parseLambdaBlockBody(): Pipeline {\n    const openBrace = this.lexer.next(); // consume `{`\n    if (this.lexer.peek().type === TokenType.RBrace) {\n      throw new ParseError(\n        `Expected at least one statement inside the lookup callback's block body at position ${openBrace.pos}`,\n        openBrace.pos,\n      );\n    }\n    const stmts: PipelineStmt[] = [this.collectStatement()];\n    while (this.lexer.peek().type === TokenType.Semi) {\n      this.lexer.next();\n      if (this.lexer.peek().type === TokenType.RBrace) break;\n      stmts.push(this.collectStatement());\n    }\n    const closeTok = this.lexer.peek();\n    if (closeTok.type !== TokenType.RBrace) {\n      throw new ParseError(\n        `Expected '}' to close the lookup callback's block body at position ${closeTok.pos}`,\n        closeTok.pos,\n      );\n    }\n    this.lexer.next(); // consume `}`\n    return { type: \"Pipeline\", stmts, pos: openBrace.pos };\n  }\n\n  /** \"new Date()\" / \"new Date(expr)\" or \"new Set()\" / \"new Set(expr)\" */\n  private parseNewDate(): Expr {\n    const newTok = this.lexer.next(); // consume 'new'\n    const className = this.lexer.peek();\n    if (className.type !== TokenType.Ident) {\n      throw new ParseError(`Expected class name after 'new' at position ${newTok.pos}`, newTok.pos);\n    }\n    if (className.value !== \"Date\" && className.value !== \"Set\") {\n      throw new ParseError(\n        `Unsupported 'new ${className.value}' at position ${className.pos}. Supported: new Date(), new Set()`,\n        className.pos,\n      );\n    }\n    const cls = className.value;\n    this.lexer.next(); // consume class name\n    this.lexer.expect(TokenType.LParen);\n    if (this.lexer.peek().type === TokenType.RParen) {\n      this.lexer.next();\n      return cls === \"Date\"\n        ? { type: \"NewDate\", args: [], pos: newTok.pos }\n        : { type: \"NewSet\", arg: null, pos: newTok.pos };\n    }\n    const args: Expr[] = [this.parseExpression()];\n    while (this.lexer.peek().type === TokenType.Comma) {\n      this.lexer.next();\n      args.push(this.parseExpression());\n    }\n    this.lexer.expect(TokenType.RParen);\n    if (cls === \"Set\") {\n      if (args.length > 1) {\n        throw new ParseError(\n          `'new Set(...)' takes 0 or 1 arguments, got ${args.length} at position ${newTok.pos}`,\n          newTok.pos,\n        );\n      }\n      return { type: \"NewSet\", arg: args[0], pos: newTok.pos };\n    }\n    if (args.length > 7) {\n      throw new ParseError(\n        `'new Date(year, month, day, hour, minute, second, ms)' takes at most 7 arguments, got ${args.length} at position ${newTok.pos}`,\n        newTok.pos,\n      );\n    }\n    return { type: \"NewDate\", args, pos: newTok.pos };\n  }\n\n  /** \"Date.now()\" or \"Date.UTC(year, month, day, \u2026)\" \u2014 other Date.* members are not supported */\n  private parseDateStatic(): Expr {\n    const dateTok = this.lexer.next(); // consume 'Date'\n    this.lexer.expect(TokenType.Dot);\n    const methodTok = this.lexer.peek();\n    if (methodTok.type !== TokenType.Ident) {\n      throw new ParseError(`Expected Date method name at position ${methodTok.pos}`, methodTok.pos);\n    }\n    if (methodTok.value === \"now\") {\n      this.lexer.next(); // consume 'now'\n      this.lexer.expect(TokenType.LParen);\n      this.lexer.expect(TokenType.RParen);\n      return { type: \"DateNow\", pos: dateTok.pos };\n    }\n    if (methodTok.value === \"UTC\") {\n      this.lexer.next(); // consume 'UTC'\n      this.lexer.expect(TokenType.LParen);\n      const args: Expr[] = [];\n      if (this.lexer.peek().type !== TokenType.RParen) {\n        args.push(this.parseExpression());\n        while (this.lexer.peek().type === TokenType.Comma) {\n          this.lexer.next();\n          args.push(this.parseExpression());\n        }\n      }\n      this.lexer.expect(TokenType.RParen);\n      if (args.length < 1 || args.length > 7) {\n        throw new ParseError(\n          `Date.UTC(year[, month, day, hour, minute, second, ms]) takes 1 to 7 arguments, got ${args.length} at position ${dateTok.pos}`,\n          dateTok.pos,\n        );\n      }\n      return { type: \"DateUTC\", args, pos: dateTok.pos };\n    }\n    throw new ParseError(\n      `Unknown Date method '${methodTok.value}' at position ${methodTok.pos}. ` +\n        `Only Date.now() and Date.UTC(\u2026) are supported as JS-style calls; for other date operations ` +\n        `use the $date* operators directly (e.g. $dateAdd, $dateDiff, $dateTrunc, $dateToString).`,\n      dateTok.pos,\n    );\n  }\n\n  /** \"Array.isArray(x)\" or \"Array.from(input)\" or \"Array.from(input, mapFn)\" */\n  private parseArrayStaticCall(): Expr {\n    const arrayTok = this.lexer.next(); // consume 'Array'\n    this.lexer.expect(TokenType.Dot);\n    const methodTok = this.lexer.peek();\n    if (methodTok.type !== TokenType.Ident) {\n      throw new ParseError(`Expected Array method name at position ${methodTok.pos}`, arrayTok.pos);\n    }\n    if (methodTok.value === \"isArray\") {\n      this.lexer.next();\n      this.lexer.expect(TokenType.LParen);\n      const arg = this.parseExpression();\n      this.lexer.expect(TokenType.RParen);\n      return { type: \"OperatorCall\", name: \"$isArray\", style: \"positional\", args: [arg], pos: arrayTok.pos };\n    }\n    if (methodTok.value === \"from\") {\n      this.lexer.next();\n      this.lexer.expect(TokenType.LParen);\n      const input = this.parseExpression();\n      let mapFn: Expr | null = null;\n      if (this.lexer.peek().type === TokenType.Comma) {\n        this.lexer.next();\n        const arg = this.parseArgOrLambda();\n        mapFn = arg;\n      }\n      this.lexer.expect(TokenType.RParen);\n      return { type: \"ArrayFrom\", input, mapFn, pos: arrayTok.pos };\n    }\n    const arrayHint = didYouMean(methodTok.value, [\"isArray\", \"from\"], (s) => `Array.${s}`);\n    throw new ParseError(\n      `Unknown Array method '${methodTok.value}' at position ${methodTok.pos}.${arrayHint} Supported: Array.isArray(), Array.from().`,\n      arrayTok.pos,\n    );\n  }\n\n  /** \"Number.isInteger(x)\" / \"Number.isNaN(x)\" / \"Number.isFinite(x)\" */\n  private parseNumberStaticCall(): Expr {\n    const numberTok = this.lexer.next(); // consume 'Number'\n    this.lexer.expect(TokenType.Dot);\n    const methodTok = this.lexer.peek();\n    if (methodTok.type !== TokenType.Ident || !(NUMBER_STATICS as readonly string[]).includes(methodTok.value)) {\n      const numberHint = didYouMean(methodTok.value, NUMBER_STATICS, (s) => `Number.${s}`);\n      throw new ParseError(\n        `Unknown Number static method '${methodTok.value}' at position ${methodTok.pos}.${numberHint} Supported: ${NUMBER_STATICS.map((s) => `Number.${s}`).join(\", \")}.`,\n        numberTok.pos,\n      );\n    }\n    const method = methodTok.value as NumberStaticMethod;\n    this.lexer.next();\n    this.lexer.expect(TokenType.LParen);\n    const arg = this.parseExpression();\n    this.lexer.expect(TokenType.RParen);\n    return { type: \"NumberStatic\", method, arg, pos: numberTok.pos };\n  }\n\n  /** \"Math.method(args)\" or \"Math.PI\" / \"Math.E\" constants */\n  private parseMathReference(): Expr {\n    const mathTok = this.lexer.next(); // consume 'Math'\n    this.lexer.expect(TokenType.Dot);\n    const ident = this.lexer.peek();\n    if (ident.type !== TokenType.Ident) {\n      throw new ParseError(`Expected Math member name at position ${ident.pos}`, mathTok.pos);\n    }\n    if (MATH_CONSTANTS.has(ident.value)) {\n      this.lexer.next(); // consume constant name\n      return { type: \"MathConst\", name: ident.value as MathConstant, pos: mathTok.pos };\n    }\n    if (!MATH_METHODS.has(ident.value)) {\n      const hint = didYouMean(ident.value, [...MATH_METHODS, ...MATH_CONSTANTS], (s) => `Math.${s}`);\n      throw new ParseError(\n        `Unknown Math member '${ident.value}' at position ${ident.pos}.${hint} See docs/LANGUAGE.md for the full list of supported Math methods and constants.`,\n        mathTok.pos,\n      );\n    }\n    this.lexer.next(); // consume method name\n    const method = ident.value as MathMethod;\n    // Bare callable form (no parens) \u2014 `.map(Math.floor)` desugars to\n    // `.map(v => Math.floor(v))`. Restricted to unary methods so the bare\n    // reference's arity matches the JS callback contract. Binary methods\n    // (pow, min, max, hypot, atan2) require explicit parens.\n    if (this.lexer.peek().type !== TokenType.LParen) {\n      if (!UNARY_MATH_CALLABLES.has(method)) {\n        throw new ParseError(\n          `Math.${method} requires '(...)'. Only the unary Math methods (Math.floor / .ceil / .round / .abs / \u2026) can be passed as bare callbacks (e.g. \\`arr.map(Math.floor)\\`).`,\n          mathTok.pos,\n        );\n      }\n      return { type: \"MathCallRef\", method, pos: mathTok.pos };\n    }\n    this.lexer.expect(TokenType.LParen);\n    const args: CallArg[] = [];\n    if (this.lexer.peek().type !== TokenType.RParen) {\n      args.push(this.parseCallArg());\n      while (this.lexer.peek().type === TokenType.Comma) {\n        this.lexer.next();\n        args.push(this.parseCallArg());\n      }\n    }\n    this.lexer.expect(TokenType.RParen);\n    return { type: \"MathCall\", method, args, pos: mathTok.pos };\n  }\n\n  /** \"Object.method(args)\" */\n  private parseObjectCall(): Expr {\n    const objectTok = this.lexer.next(); // consume 'Object'\n    this.lexer.expect(TokenType.Dot);\n    const methodTok = this.lexer.peek();\n    if (methodTok.type !== TokenType.Ident || !OBJECT_METHODS.has(methodTok.value)) {\n      const objectHint = didYouMean(methodTok.value, [...OBJECT_METHODS], (s) => `Object.${s}`);\n      throw new ParseError(\n        `Unknown Object method '${methodTok.value}' at position ${methodTok.pos}.${objectHint} Supported: ${[...OBJECT_METHODS].join(\", \")}.`,\n        objectTok.pos,\n      );\n    }\n    this.lexer.next(); // consume method name\n    const method = methodTok.value as ObjectMethod;\n    this.lexer.expect(TokenType.LParen);\n    const args: CallArg[] = [];\n    if (this.lexer.peek().type !== TokenType.RParen) {\n      args.push(this.parseCallArg());\n      while (this.lexer.peek().type === TokenType.Comma) {\n        this.lexer.next();\n        args.push(this.parseCallArg());\n      }\n    }\n    this.lexer.expect(TokenType.RParen);\n    return { type: \"ObjectCall\", method, args, pos: objectTok.pos };\n  }\n\n  /** \"Number(x)\" | \"String(x)\" | \"Boolean(x)\" | \"parseInt(x)\" | \"parseFloat(x)\" */\n  private parseTypeCast(): Expr {\n    const castTok = this.lexer.next(); // consume cast name\n    const cast = castTok.value as TypeCastOp;\n    this.lexer.expect(TokenType.LParen);\n    const arg = this.parseExpression();\n    if (this.lexer.peek().type === TokenType.Comma) {\n      throw new ParseError(`Type cast '${cast}()' takes exactly 1 argument at position ${castTok.pos}`, castTok.pos);\n    }\n    this.lexer.expect(TokenType.RParen);\n    return { type: \"TypeCast\", cast, arg, pos: castTok.pos };\n  }\n\n  private parseNumber(): Expr {\n    const t = this.lexer.next();\n    const value = parseFloat(t.value);\n    if (isNaN(value)) {\n      throw new ParseError(`Invalid number '${t.value}' at position ${t.pos}`, t.pos);\n    }\n    return { type: \"NumberLiteral\", value, pos: t.pos };\n  }\n\n  /** Parse a template literal: `chunk0${expr0}chunk1${expr1}chunk2` */\n  private parseTemplateLiteral(): Expr {\n    const startTok = this.lexer.expect(TokenType.TemplateStart);\n    const quasis: string[] = [];\n    const expressions: Expr[] = [];\n\n    for (;;) {\n      const chunk = this.lexer.expect(TokenType.TemplateChars);\n      quasis.push(chunk.value);\n      const next = this.lexer.peek();\n      if (next.type === TokenType.TemplateEnd) {\n        this.lexer.next();\n        break;\n      }\n      if (next.type === TokenType.TemplateExprStart) {\n        this.lexer.next();\n        const expr = this.parseExpression();\n        // The closing `}` of `${...}` is consumed by the lexer's brace-tracking logic,\n        // which switches back to template-chunk reading without emitting an RBrace.\n        // So the next token should be another TemplateChars chunk.\n        expressions.push(expr);\n        continue;\n      }\n      throw new ParseError(`Unexpected token in template literal at position ${next.pos}`, next.pos);\n    }\n\n    return { type: \"TemplateLiteral\", quasis, expressions, pos: startTok.pos };\n  }\n\n  private parseArrayLiteral(): Expr {\n    const openBracket = this.lexer.expect(TokenType.LBracket);\n    const elements: ArrayElement[] = [];\n\n    while (this.lexer.peek().type !== TokenType.RBracket) {\n      if (this.lexer.peek().type === TokenType.EOF) {\n        throw new ParseError(\"Unterminated array literal\", this.lexer.peek().pos);\n      }\n      if (this.lexer.peek().type === TokenType.Spread) {\n        const spreadTok = this.lexer.next();\n        const arg = this.parseExpression();\n        const spread: SpreadElement = { type: \"SpreadElement\", argument: arg, pos: spreadTok.pos };\n        elements.push(spread);\n      } else if (this.lexer.peek().type === TokenType.Delete) {\n        // `delete $.x` as a pipeline element. Codegen rejects it if the array\n        // turns out not to be a pipeline.\n        elements.push(this.parseDeleteStmt());\n      } else if (this.lexer.peek().type === TokenType.Let) {\n        // `let x = expr` as a pipeline element. Codegen rejects it if the\n        // array is not a pipeline (parallel to AssignExpr/DeleteStmt handling).\n        elements.push(this.parseLetDecl());\n      } else if (this.peekIncDecOp() !== null) {\n        // Prefix `++$.x` / `--$.x` as a pipeline element.\n        elements.push(this.parsePrefixIncDec());\n      } else {\n        // Could be a regular expression OR an assignment OR a postfix `x++`\n        // used as a pipeline element. Parse the expression first; if a bare\n        // assignment operator or `++`/`--` follows, treat as a update op.\n        const expr = this.parseExpression();\n        if (this.peekAssignOp() !== null) {\n          this.validateUpdateTarget(expr);\n          for (const m of this.parseAssignmentChainFrom(expr)) elements.push(m);\n        } else if (this.peekIncDecOp() !== null) {\n          const op = this.peekIncDecOp()!;\n          this.lexer.next();\n          this.validateUpdateTarget(expr);\n          elements.push(this.makeIncDecUpdateOp(expr, op));\n        } else {\n          elements.push(expr);\n        }\n      }\n      if (this.lexer.peek().type === TokenType.Comma) {\n        this.lexer.next();\n      } else {\n        break;\n      }\n    }\n\n    this.lexer.expect(TokenType.RBracket);\n    return { type: \"ArrayLiteral\", elements, pos: openBracket.pos };\n  }\n\n  private parseObjectLiteral(): Expr {\n    const openBrace = this.lexer.expect(TokenType.LBrace);\n    const entries: ObjectEntry[] = [];\n\n    while (this.lexer.peek().type !== TokenType.RBrace) {\n      if (this.lexer.peek().type === TokenType.EOF) {\n        throw new ParseError(\"Unterminated object literal\", this.lexer.peek().pos);\n      }\n      if (this.lexer.peek().type === TokenType.Spread) {\n        const spreadTok = this.lexer.next();\n        const arg = this.parseExpression();\n        const spread: SpreadElement = { type: \"SpreadElement\", argument: arg, pos: spreadTok.pos };\n        entries.push(spread);\n      } else {\n        entries.push(this.parseObjectEntry());\n      }\n      if (this.lexer.peek().type === TokenType.Comma) {\n        this.lexer.next();\n      } else {\n        break;\n      }\n    }\n\n    this.lexer.expect(TokenType.RBrace);\n    return { type: \"ObjectLiteral\", entries, pos: openBrace.pos };\n  }\n\n  /**\n   * Parse one non-spread object entry. Supports:\n   *   - Static key:    `name: expr`  or  `\"name\": expr`\n   *   - Computed key:  `[expr]: expr`\n   *   - Shorthand:     `name`  (sugar for `name: name`, valid in lambda scope)\n   */\n  private parseObjectEntry(): KeyValueEntry {\n    const tok = this.lexer.peek();\n\n    // Computed key: [expr]: value\n    if (tok.type === TokenType.LBracket) {\n      this.lexer.next();\n      const keyExpr = this.parseExpression();\n      this.lexer.expect(TokenType.RBracket);\n      this.lexer.expect(TokenType.Colon);\n      const value = this.parseExpression();\n      const key: ObjectKey = { kind: \"computed\", expr: keyExpr };\n      return { type: \"KeyValueEntry\", key, value, pos: tok.pos };\n    }\n\n    // `$ident:` form. In JS, `$match` is a valid identifier; the lexer splits\n    // it into Dollar + Ident so `$match(...)` and `$.foo` can be recognised\n    // distinctly. As an object key we re-stitch them: `{ $match: ... }`,\n    // `{ $gt: 18 }`, `{ $or: [...] }` are the natural ways to author\n    // aggregation stage objects and MongoDB query documents.\n    if (tok.type === TokenType.Dollar) {\n      this.lexer.next();\n      const ident = this.lexer.peek();\n      if (!this.isIdentOrKeyword(ident)) {\n        throw new ParseError(`Expected identifier after '$' at position ${tok.pos}`, tok.pos);\n      }\n      this.lexer.next();\n      this.lexer.expect(TokenType.Colon);\n      const value = this.parseExpression();\n      const key: ObjectKey = { kind: \"static\", name: `$${ident.value}` };\n      return { type: \"KeyValueEntry\", key, value, pos: tok.pos };\n    }\n\n    // `let` is a jsmql keyword but is also a legitimate MongoDB object-key name\n    // (`$lookup`, `$graphLookup`, `$documents`, and top-level `aggregate({ let: ... })`\n    // all carry a `let:` field). Accept it as an object key so those stage shapes\n    // continue to parse. Shorthand `{ let }` is intentionally rejected \u2014 that\n    // would conflict with `let x = \u2026` statements and serve no useful purpose.\n    if (tok.type === TokenType.Let) {\n      this.lexer.next();\n      this.lexer.expect(TokenType.Colon);\n      const value = this.parseExpression();\n      const key: ObjectKey = { kind: \"static\", name: \"let\" };\n      return { type: \"KeyValueEntry\", key, value, pos: tok.pos };\n    }\n\n    if (tok.type !== TokenType.Ident && tok.type !== TokenType.String) {\n      throw new ParseError(`Expected object key at position ${tok.pos}`, tok.pos);\n    }\n    this.lexer.next();\n    const next = this.lexer.peek();\n    // Shorthand: `{ x }` \u2014 only valid for plain identifiers; it desugars to `{ x: x }`,\n    // where the value is a ParamRef. (Codegen will reject if `x` is not a lambda param.)\n    if (tok.type === TokenType.Ident && (next.type === TokenType.Comma || next.type === TokenType.RBrace)) {\n      const key: ObjectKey = { kind: \"static\", name: tok.value };\n      const value: Expr = { type: \"ParamRef\", name: tok.value, pos: tok.pos };\n      return { type: \"KeyValueEntry\", key, value, pos: tok.pos };\n    }\n    this.lexer.expect(TokenType.Colon);\n    const value = this.parseExpression();\n    const key: ObjectKey = { kind: \"static\", name: tok.value };\n    return { type: \"KeyValueEntry\", key, value, pos: tok.pos };\n  }\n}\n\n/**\n * Human-friendly noun phrase for an Expr that the user tried to use as a\n * update op target. Used by `validateUpdateTarget` to name *what* the user\n * wrote (a method call, a comparison, a literal, \u2026) rather than just\n * complaining the target wasn't a field path.\n */\n/**\n * Walk a receiver chain back to its root and report whether the root is one\n * of the lookup-receiver context-ref prefixes \u2014 `DatabaseRef` (`$$$`, same\n * database) or `ClusterRef` (`$$$$`, cross-database). Used by `parsePostfix`\n * to decide whether a `.find(...)` / `.filter(...)` method call should accept\n * the lookup-callback grammar (block-body lambda, future-resolved as a\n * `$lookup` sub-pipeline).\n *\n * The chain may include any number of `MemberAccess` and `IndexAccess` hops\n * (so `$$$.users`, `$$$[\"users\"]`, `$$$$.myDb.myColl`, `$$$$[\"db\"][\"coll\"]`,\n * and the mixed bracket combos all match); method calls and other expression\n * shapes do not \u2014 only direct property navigation off the context ref is the\n * lookup-receiver shape. Depth-checking (rejecting `$$$.foo.bar.find(...)`\n * or `$$$$.db.coll.extra.find(...)`) happens at the codegen / lookup-\n * translation layer (`extractLookupTarget` requires exactly one or two\n * static-access levels).\n */\nfunction isLookupReceiverRooted(expr: Expr): boolean {\n  let node: Expr = expr;\n  for (;;) {\n    if (node.type === \"DatabaseRef\" || node.type === \"ClusterRef\") return true;\n    if (node.type === \"MemberAccess\") {\n      node = node.object;\n      continue;\n    }\n    if (node.type === \"IndexAccess\") {\n      node = node.object;\n      continue;\n    }\n    return false;\n  }\n}\n\nfunction describeUpdateTarget(target: Expr): string {\n  switch (target.type) {\n    case \"MethodCall\":\n      return `a method-call result ('.${target.method}()')`;\n    case \"CallExpression\":\n      return \"a call result\";\n    case \"BinaryExpr\":\n      return `a '${target.op}' expression`;\n    case \"UnaryExpr\":\n      return `a unary '${target.op}' expression`;\n    case \"TernaryExpr\":\n      return \"a ternary expression\";\n    case \"TypeCast\":\n      return `a '${target.cast}()' cast`;\n    case \"TypeCastRef\":\n      return `a bare '${target.cast}' reference`;\n    case \"MemberAccess\":\n      return \"a member access whose root is not a field path\";\n    case \"Lambda\":\n      return \"a lambda expression\";\n    case \"ArrayLiteral\":\n      return \"an array literal\";\n    case \"ObjectLiteral\":\n      return \"an object literal\";\n    case \"NumberLiteral\":\n    case \"BigIntLiteral\":\n    case \"StringLiteral\":\n    case \"BooleanLiteral\":\n    case \"NullLiteral\":\n      return \"a literal value\";\n    case \"TemplateLiteral\":\n      return \"a template literal\";\n    case \"OperatorCall\":\n      return `the result of ${target.name}(\u2026)`;\n    case \"MathCall\":\n      return `the result of Math.${target.method}(\u2026)`;\n    case \"MathCallRef\":\n      return `a bare 'Math.${target.method}' reference`;\n    case \"MathConst\":\n      return `the Math.${target.name} constant`;\n    case \"ObjectCall\":\n      return `the result of Object.${target.method}(\u2026)`;\n    case \"NewDate\":\n      return \"a 'new Date(\u2026)' expression\";\n    case \"NewSet\":\n      return \"a 'new Set(\u2026)' expression\";\n    case \"DateNow\":\n      return \"the result of Date.now()\";\n    case \"DateUTC\":\n      return \"the result of Date.UTC(\u2026)\";\n    case \"ArrayFrom\":\n      return \"an Array.from(\u2026) result\";\n    case \"NumberStatic\":\n      return `the result of Number.${target.method}(\u2026)`;\n    case \"TypeofExpr\":\n      return \"a typeof expression\";\n    case \"RegexLiteral\":\n      return \"a regex literal\";\n    default:\n      return \"this expression\";\n  }\n}\n", "export type SingleShape = { kind: \"single\" };\nexport type ArrayShape = { kind: \"array\" };\nexport type ObjectShape = { kind: \"object\"; keys: string[] };\nexport type NoneShape = { kind: \"none\" };\n// Flex: operator accepts either a single expression OR an array of expressions.\n// Used for MQL operators that legitimately have two shapes (e.g. accumulator vs\n// expression context). 1 arg \u2192 `{ $op: expr }`, 2+ args \u2192 `{ $op: [a, b, ...] }`.\nexport type FlexShape = { kind: \"flex\" };\n\nexport type OperatorShape = SingleShape | ArrayShape | ObjectShape | NoneShape | FlexShape;\n\nexport const OPERATOR_CATEGORIES = [\n  \"arithmetic\",\n  \"array\",\n  \"bitwise\",\n  \"boolean\",\n  \"comparison\",\n  \"conditional\",\n  \"custom-aggregation\",\n  \"data-size\",\n  \"date\",\n  \"encrypted-string\",\n  \"literal\",\n  \"miscellaneous\",\n  \"object\",\n  \"set\",\n  \"string\",\n  \"text\",\n  \"timestamp\",\n  \"trigonometry\",\n  \"type\",\n  \"variable\",\n  \"window\",\n] as const;\nexport type OperatorCategory = (typeof OPERATOR_CATEGORIES)[number];\n\nexport type OperatorDef = {\n  shape: OperatorShape;\n  category: OperatorCategory;\n  description: string;\n  // Accumulator-only operators (`$push`, `$addToSet`, `$top`, \u2026) are valid only\n  // inside `$group` field-value slots or `$setWindowFields` output slots. Codegen\n  // gates them on this flag \u2014 it is the single source of truth, so adding an\n  // accumulator-only operator is one edit here (no shadow set in codegen). Ops\n  // that have *both* expression and accumulator forms ($sum, $avg, $max, \u2026) are\n  // unrestricted and leave this unset.\n  accumulatorOnly?: boolean;\n};\n\nconst SINGLE: SingleShape = { kind: \"single\" };\nconst ARRAY: ArrayShape = { kind: \"array\" };\nconst NONE: NoneShape = { kind: \"none\" };\nconst FLEX: FlexShape = { kind: \"flex\" };\n\nfunction single(category: OperatorCategory, description: string): OperatorDef {\n  return { shape: SINGLE, category, description };\n}\nfunction array(category: OperatorCategory, description: string): OperatorDef {\n  return { shape: ARRAY, category, description };\n}\nfunction none(category: OperatorCategory, description: string): OperatorDef {\n  return { shape: NONE, category, description };\n}\nfunction flex(category: OperatorCategory, description: string): OperatorDef {\n  return { shape: FLEX, category, description };\n}\nfunction obj(category: OperatorCategory, description: string, ...keys: string[]): OperatorDef {\n  return { shape: { kind: \"object\", keys }, category, description };\n}\n// Mark a built operator def as accumulator-only (valid only inside `$group` /\n// `$setWindowFields` output). Wraps any of the shape factories: `acc(single(...))`.\nfunction acc(def: OperatorDef): OperatorDef {\n  return { ...def, accumulatorOnly: true };\n}\n\nexport const OPERATORS: Record<string, OperatorDef> = {\n  // \u2500\u2500 Arithmetic \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $abs: single(\"arithmetic\", \"Returns the absolute value of a number.\"),\n  $add: array(\"arithmetic\", \"Adds numbers to return the sum, or adds numbers and a date to return a new date.\"),\n  $ceil: single(\"arithmetic\", \"Returns the smallest integer greater than or equal to the specified number.\"),\n  $divide: array(\"arithmetic\", \"Returns the result of dividing the first number by the second.\"),\n  $exp: single(\"arithmetic\", \"Raises e to the specified exponent.\"),\n  $floor: single(\"arithmetic\", \"Returns the largest integer less than or equal to the specified number.\"),\n  $ln: single(\"arithmetic\", \"Calculates the natural log of a number.\"),\n  $log: array(\"arithmetic\", \"Calculates the log of a number in the specified base.\"),\n  $log10: single(\"arithmetic\", \"Calculates the log base 10 of a number.\"),\n  $mod: array(\"arithmetic\", \"Returns the remainder of the first number divided by the second.\"),\n  $multiply: array(\"arithmetic\", \"Multiplies numbers to return the product.\"),\n  $pow: array(\"arithmetic\", \"Raises a number to the specified exponent.\"),\n  $round: flex(\"arithmetic\", \"Rounds a number to a whole integer or to a specified decimal place.\"),\n  $sigmoid: single(\n    \"arithmetic\",\n    \"Returns the sigmoid of a value, defined as 1 / (1 + e^(-x)). The result is between 0 and 1.\",\n  ),\n  $sqrt: single(\"arithmetic\", \"Calculates the square root.\"),\n  $subtract: array(\"arithmetic\", \"Returns the result of subtracting the second value from the first.\"),\n  $trunc: flex(\"arithmetic\", \"Truncates a number to a whole integer or to a specified decimal place.\"),\n\n  // \u2500\u2500 Bitwise \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $bitAnd: array(\"bitwise\", \"Returns the result of a bitwise AND operation on an array of int or long values.\"),\n  $bitNot: single(\"bitwise\", \"Returns the result of a bitwise NOT operation on a single int or long value.\"),\n  $bitOr: array(\"bitwise\", \"Returns the result of a bitwise OR operation on an array of int or long values.\"),\n  $bitXor: array(\n    \"bitwise\",\n    \"Returns the result of a bitwise XOR (exclusive or) operation on an array of int and long values.\",\n  ),\n\n  // \u2500\u2500 Trigonometry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $sin: single(\"trigonometry\", \"Returns the sine of a value that is measured in radians.\"),\n  $cos: single(\"trigonometry\", \"Returns the cosine of a value that is measured in radians.\"),\n  $tan: single(\"trigonometry\", \"Returns the tangent of a value that is measured in radians.\"),\n  $asin: single(\"trigonometry\", \"Returns the inverse sine (arc sine) of a value in radians.\"),\n  $acos: single(\"trigonometry\", \"Returns the inverse cosine (arc cosine) of a value in radians.\"),\n  $atan: single(\"trigonometry\", \"Returns the inverse tangent (arc tangent) of a value in radians.\"),\n  $atan2: array(\n    \"trigonometry\",\n    \"Returns the inverse tangent of y / x in radians, where y and x are the first and second arguments.\",\n  ),\n  $sinh: single(\"trigonometry\", \"Returns the hyperbolic sine of a value measured in radians.\"),\n  $cosh: single(\"trigonometry\", \"Returns the hyperbolic cosine of a value measured in radians.\"),\n  $tanh: single(\"trigonometry\", \"Returns the hyperbolic tangent of a value measured in radians.\"),\n  $asinh: single(\"trigonometry\", \"Returns the inverse hyperbolic sine of a value in radians.\"),\n  $acosh: single(\"trigonometry\", \"Returns the inverse hyperbolic cosine of a value in radians.\"),\n  $atanh: single(\"trigonometry\", \"Returns the inverse hyperbolic tangent of a value in radians.\"),\n  $degreesToRadians: single(\"trigonometry\", \"Converts a value from degrees to radians.\"),\n  $radiansToDegrees: single(\"trigonometry\", \"Converts a value from radians to degrees.\"),\n\n  // \u2500\u2500 Comparison \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $cmp: array(\"comparison\", \"Returns 0 if the two values are equivalent, 1 if the first is greater, and -1 if less.\"),\n  $eq: array(\"comparison\", \"Returns true if the values are equivalent.\"),\n  $ne: array(\"comparison\", \"Returns true if the values are not equivalent.\"),\n  $gt: array(\"comparison\", \"Returns true if the first value is greater than the second.\"),\n  $gte: array(\"comparison\", \"Returns true if the first value is greater than or equal to the second.\"),\n  $lt: array(\"comparison\", \"Returns true if the first value is less than the second.\"),\n  $lte: array(\"comparison\", \"Returns true if the first value is less than or equal to the second.\"),\n\n  // \u2500\u2500 Boolean \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $and: array(\"boolean\", \"Returns true only when all its expressions evaluate to true.\"),\n  $or: array(\"boolean\", \"Returns true when any of its expressions evaluates to true.\"),\n  $not: single(\"boolean\", \"Returns the boolean value that is the opposite of its argument expression.\"),\n\n  // \u2500\u2500 Conditional \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $cond: obj(\n    \"conditional\",\n    \"A ternary operator that evaluates one expression and returns one of two other expressions based on the result.\",\n    \"if\",\n    \"then\",\n    \"else\",\n  ),\n  $ifNull: array(\n    \"conditional\",\n    \"Returns either the non-null result of the first expression or the result of the second expression.\",\n  ),\n  $switch: obj(\n    \"conditional\",\n    \"Evaluates a series of case expressions; executes the matching case's expression and breaks out of the control flow.\",\n    \"branches\",\n    \"default\",\n  ),\n\n  // \u2500\u2500 String \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $concat: array(\"string\", \"Concatenates any number of strings.\"),\n  $indexOfBytes: array(\n    \"string\",\n    \"Searches a string for a substring and returns the UTF-8 byte index of the first occurrence, or -1.\",\n  ),\n  $indexOfCP: array(\n    \"string\",\n    \"Searches a string for a substring and returns the UTF-8 code point index of the first occurrence, or -1.\",\n  ),\n  $ltrim: obj(\n    \"string\",\n    \"Removes whitespace or the specified characters from the beginning of a string.\",\n    \"input\",\n    \"chars\",\n  ),\n  $rtrim: obj(\"string\", \"Removes whitespace or the specified characters from the end of a string.\", \"input\", \"chars\"),\n  $trim: obj(\n    \"string\",\n    \"Removes whitespace or the specified characters from the beginning and end of a string.\",\n    \"input\",\n    \"chars\",\n  ),\n  $regexFind: obj(\n    \"string\",\n    \"Applies a regular expression to a string and returns information on the first matched substring.\",\n    \"input\",\n    \"regex\",\n    \"options\",\n  ),\n  $regexFindAll: obj(\n    \"string\",\n    \"Applies a regular expression to a string and returns information on all matched substrings.\",\n    \"input\",\n    \"regex\",\n    \"options\",\n  ),\n  $regexMatch: obj(\n    \"string\",\n    \"Applies a regular expression to a string and returns a boolean indicating whether a match is found.\",\n    \"input\",\n    \"regex\",\n    \"options\",\n  ),\n  $replaceAll: obj(\n    \"string\",\n    \"Replaces all instances of a search string in an input string with a replacement string.\",\n    \"input\",\n    \"find\",\n    \"replacement\",\n  ),\n  $replaceOne: obj(\n    \"string\",\n    \"Replaces the first instance of a matched string in a given input.\",\n    \"input\",\n    \"find\",\n    \"replacement\",\n  ),\n  $split: array(\"string\", \"Splits a string into substrings based on a delimiter and returns an array of substrings.\"),\n  $strLenBytes: single(\"string\", \"Returns the number of UTF-8 encoded bytes in a string.\"),\n  $strLenCP: single(\"string\", \"Returns the number of UTF-8 code points in a string.\"),\n  $strcasecmp: array(\"string\", \"Performs case-insensitive string comparison.\"),\n  $substr: array(\"string\", \"Deprecated. Use $substrBytes or $substrCP.\"),\n  $substrBytes: array(\"string\", \"Returns the substring of a string starting at the specified UTF-8 byte index.\"),\n  $substrCP: array(\"string\", \"Returns the substring of a string starting at the specified UTF-8 code point index.\"),\n  $toLower: single(\"string\", \"Converts a string to lowercase.\"),\n  $toUpper: single(\"string\", \"Converts a string to uppercase.\"),\n\n  // \u2500\u2500 Encrypted String (Queryable Encryption) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  // Not in mongodb/mql-specifications as of pinned commit; allowlisted in the\n  // drift test. Shapes inferred from the MongoDB documentation.\n  $encStrContains: obj(\n    \"encrypted-string\",\n    \"Returns true if a substring exists within the encrypted string.\",\n    \"input\",\n    \"substring\",\n  ),\n  $encStrEndsWith: obj(\n    \"encrypted-string\",\n    \"Returns true if the encrypted string ends with the specified suffix.\",\n    \"input\",\n    \"suffix\",\n  ),\n  $encStrNormalizedEq: obj(\n    \"encrypted-string\",\n    \"Returns true if the normalized encrypted string equals the specified string.\",\n    \"input\",\n    \"string\",\n  ),\n  $encStrStartsWith: obj(\n    \"encrypted-string\",\n    \"Returns true if the encrypted string starts with the specified prefix.\",\n    \"input\",\n    \"prefix\",\n  ),\n\n  // \u2500\u2500 Array \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $arrayElemAt: array(\"array\", \"Returns the element at the specified array index.\"),\n  $arrayToObject: single(\"array\", \"Converts an array of key-value pairs to a document.\"),\n  $concatArrays: array(\"array\", \"Concatenates arrays to return the concatenated array.\"),\n  $filter: obj(\n    \"array\",\n    \"Selects a subset of the array, returning only elements that match the filter condition.\",\n    \"input\",\n    \"as\",\n    \"cond\",\n    \"limit\",\n  ),\n  $first: single(\"array\", \"Returns the result of an expression for the first document in an array.\"),\n  $firstN: obj(\"array\", \"Returns a specified number of elements from the beginning of an array.\", \"input\", \"n\"),\n  $in: array(\"array\", \"Returns a boolean indicating whether a specified value is in an array.\"),\n  $indexOfArray: array(\"array\", \"Searches an array for a value and returns the index of the first occurrence, or -1.\"),\n  $isArray: single(\"array\", \"Determines if the operand is an array.\"),\n  $last: single(\"array\", \"Returns the result of an expression for the last document in an array.\"),\n  $lastN: obj(\"array\", \"Returns a specified number of elements from the end of an array.\", \"input\", \"n\"),\n  $map: obj(\n    \"array\",\n    \"Applies a subexpression to each element of an array and returns the array of resulting values.\",\n    \"input\",\n    \"as\",\n    \"in\",\n  ),\n  $maxN: obj(\"array\", \"Returns the n largest values in an array.\", \"input\", \"n\"),\n  $minN: obj(\"array\", \"Returns the n smallest values in an array.\", \"input\", \"n\"),\n  $objectToArray: single(\"array\", \"Converts a document to an array of documents representing key-value pairs.\"),\n  $range: array(\"array\", \"Outputs an array containing a sequence of integers according to user-defined inputs.\"),\n  $reduce: obj(\n    \"array\",\n    \"Applies an expression to each element in an array and combines them into a single value.\",\n    \"input\",\n    \"initialValue\",\n    \"in\",\n  ),\n  $reverseArray: single(\"array\", \"Returns an array with the elements in reverse order.\"),\n  $size: single(\"array\", \"Returns the number of elements in the array.\"),\n  $slice: array(\"array\", \"Returns a subset of an array.\"),\n  $sortArray: obj(\"array\", \"Sorts the elements of an array.\", \"input\", \"sortBy\"),\n  $zip: obj(\n    \"array\",\n    \"Merges two or more arrays element-wise into a single array of arrays.\",\n    \"inputs\",\n    \"useLongestLength\",\n    \"defaults\",\n  ),\n\n  // \u2500\u2500 Set \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $allElementsTrue: single(\"set\", \"Returns true if no element of a set evaluates to false.\"),\n  $anyElementTrue: single(\"set\", \"Returns true if any elements of a set evaluate to true.\"),\n  $setDifference: array(\"set\", \"Returns a set with elements that appear in the first set but not in the second set.\"),\n  $setEquals: array(\"set\", \"Returns true if the input sets have the same distinct elements.\"),\n  $setIntersection: array(\"set\", \"Returns a set with elements that appear in all of the input sets.\"),\n  $setIsSubset: array(\"set\", \"Returns true if all elements of the first set appear in the second set.\"),\n  $setUnion: array(\"set\", \"Returns a set with elements that appear in any of the input sets.\"),\n\n  // \u2500\u2500 Object \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $getField: obj(\n    \"object\",\n    \"Returns the value of a specified field from a document, including fields whose names contain periods or start with $.\",\n    \"field\",\n    \"input\",\n  ),\n  $mergeObjects: flex(\"object\", \"Combines multiple documents into a single document.\"),\n  $setField: obj(\"object\", \"Adds, updates, or removes a specified field in a document.\", \"field\", \"input\", \"value\"),\n  $unsetField: obj(\n    \"object\",\n    \"Removes a specified field from a document. Alias for $setField using $$REMOVE.\",\n    \"field\",\n    \"input\",\n  ),\n\n  // \u2500\u2500 Date \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $dateAdd: obj(\"date\", \"Adds a number of time units to a date object.\", \"startDate\", \"unit\", \"amount\", \"timezone\"),\n  $dateDiff: obj(\n    \"date\",\n    \"Returns the difference between two dates.\",\n    \"startDate\",\n    \"endDate\",\n    \"unit\",\n    \"startOfWeek\",\n    \"timezone\",\n  ),\n  $dateFromParts: obj(\n    \"date\",\n    \"Constructs a BSON Date object given the date's constituent parts.\",\n    \"year\",\n    \"month\",\n    \"day\",\n    \"hour\",\n    \"minute\",\n    \"second\",\n    \"millisecond\",\n    \"timezone\",\n  ),\n  $dateFromString: obj(\n    \"date\",\n    \"Converts a date/time string to a date object.\",\n    \"dateString\",\n    \"format\",\n    \"timezone\",\n    \"onError\",\n    \"onNull\",\n  ),\n  $dateSubtract: obj(\n    \"date\",\n    \"Subtracts a number of time units from a date object.\",\n    \"startDate\",\n    \"unit\",\n    \"amount\",\n    \"timezone\",\n  ),\n  $dateToParts: obj(\n    \"date\",\n    \"Returns a document containing the constituent parts of a date.\",\n    \"date\",\n    \"timezone\",\n    \"iso8601\",\n  ),\n  $dateToString: obj(\"date\", \"Returns the date as a formatted string.\", \"date\", \"format\", \"timezone\", \"onNull\"),\n  $dateTrunc: obj(\"date\", \"Truncates a date.\", \"date\", \"unit\", \"binSize\", \"timezone\", \"startOfWeek\"),\n  $dayOfMonth: single(\"date\", \"Returns the day of the month for a date as a number between 1 and 31.\"),\n  $dayOfWeek: single(\"date\", \"Returns the day of the week for a date as a number between 1 (Sunday) and 7 (Saturday).\"),\n  $dayOfYear: single(\"date\", \"Returns the day of the year for a date as a number between 1 and 366.\"),\n  $hour: single(\"date\", \"Returns the hour for a date as a number between 0 and 23.\"),\n  $isoDayOfWeek: single(\n    \"date\",\n    \"Returns the weekday number in ISO 8601 format, ranging from 1 (Monday) to 7 (Sunday).\",\n  ),\n  $isoWeek: single(\"date\", \"Returns the week number in ISO 8601 format, ranging from 1 to 53.\"),\n  $isoWeekYear: single(\"date\", \"Returns the year number in ISO 8601 format.\"),\n  $millisecond: single(\"date\", \"Returns the milliseconds of a date as a number between 0 and 999.\"),\n  $minute: single(\"date\", \"Returns the minute for a date as a number between 0 and 59.\"),\n  $month: single(\"date\", \"Returns the month for a date as a number between 1 (January) and 12 (December).\"),\n  $second: single(\"date\", \"Returns the seconds for a date as a number between 0 and 60 (leap seconds).\"),\n  $toDate: single(\"date\", \"Converts a value to a Date.\"),\n  $week: single(\"date\", \"Returns the week number for a date as a number between 0 and 53.\"),\n  $year: single(\"date\", \"Returns the year for a date as a number.\"),\n\n  // \u2500\u2500 Timestamp \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $tsIncrement: single(\"timestamp\", \"Returns the incrementing ordinal from a timestamp as a long.\"),\n  $tsSecond: single(\"timestamp\", \"Returns the seconds from a timestamp as a long.\"),\n\n  // \u2500\u2500 Type \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $convert: obj(\"type\", \"Converts a value to a specified type.\", \"input\", \"to\", \"onError\", \"onNull\"),\n  $isNumber: single(\"type\", \"Returns true if the expression resolves to an integer, decimal, double, or long.\"),\n  $toArray: single(\"type\", \"Converts a value to an array.\"),\n  $toBool: single(\"type\", \"Converts a value to a boolean.\"),\n  $toDecimal: single(\"type\", \"Converts a value to a Decimal128.\"),\n  $toDouble: single(\"type\", \"Converts a value to a double.\"),\n  $toInt: single(\"type\", \"Converts a value to an integer.\"),\n  $toLong: single(\"type\", \"Converts a value to a long.\"),\n  $toObject: single(\"type\", \"Converts a string to an object.\"),\n  $toObjectId: single(\"type\", \"Converts a value to an ObjectId.\"),\n  $toString: single(\"type\", \"Converts a value to a string.\"),\n  $toUUID: single(\"type\", \"Converts a string to a UUID.\"),\n  $type: single(\"type\", \"Returns the BSON data type of the field.\"),\n\n  // \u2500\u2500 Literal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $literal: single(\n    \"literal\",\n    \"Returns a value without parsing. Use to keep values that the pipeline would otherwise interpret as expressions (e.g. strings starting with $).\",\n  ),\n\n  // \u2500\u2500 Variable \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $let: obj(\n    \"variable\",\n    \"Defines variables for use within the scope of a subexpression and returns the result.\",\n    \"vars\",\n    \"in\",\n  ),\n\n  // \u2500\u2500 Custom Aggregation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $accumulator: acc(\n    obj(\n      \"custom-aggregation\",\n      \"Defines a custom accumulator function. Body fields hold JavaScript source executed by the server.\",\n      \"init\",\n      \"initArgs\",\n      \"accumulate\",\n      \"accumulateArgs\",\n      \"merge\",\n      \"finalize\",\n      \"lang\",\n    ),\n  ),\n  $function: obj(\n    \"custom-aggregation\",\n    \"Defines a custom function. The body field is JavaScript source executed by the server.\",\n    \"body\",\n    \"args\",\n    \"lang\",\n  ),\n\n  // \u2500\u2500 Data Size \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $binarySize: single(\"data-size\", \"Returns the size of a string or binary data value's content in bytes.\"),\n  $bsonSize: single(\"data-size\", \"Returns the size in bytes of a document when encoded as BSON.\"),\n\n  // \u2500\u2500 Text \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $meta: single(\n    \"text\",\n    'Accesses per-document metadata related to the aggregation operation. Argument is a keyword string (e.g. \"textScore\"), not an arbitrary expression.',\n  ),\n\n  // \u2500\u2500 Miscellaneous \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $createObjectId: none(\"miscellaneous\", \"Returns a random ObjectId.\"),\n  $hash: obj(\n    \"miscellaneous\",\n    \"Generates a binary hash value (BinData) from a UTF-8 string or binary data.\",\n    \"input\",\n    \"algorithm\",\n  ),\n  $hexHash: obj(\n    \"miscellaneous\",\n    \"Generates an uppercase hexadecimal hash string from a UTF-8 string or binary data.\",\n    \"input\",\n    \"algorithm\",\n  ),\n  $rand: none(\"miscellaneous\", \"Returns a random float between 0 and 1.\"),\n  $sampleRate: single(\"miscellaneous\", \"Randomly selects documents at a given rate. Used inside $match.\"),\n  $toHashedIndexKey: single(\n    \"miscellaneous\",\n    \"Computes the hash of the input expression using MongoDB's hashed-index hash function.\",\n  ),\n\n  // \u2500\u2500 Accumulators (also valid as expression operators in some stages) \u2500\u2500\u2500\u2500\u2500\u2500\n  $addToSet: acc(single(\"array\", \"Returns an array of unique expression values for each group.\")),\n  $avg: flex(\"arithmetic\", \"Returns the average for the specified expression.\"),\n  $count: none(\"array\", \"Returns the number of documents in the group or window.\"),\n  $max: flex(\"comparison\", \"Returns the maximum value that results from applying an expression.\"),\n  $median: acc(\n    obj(\"arithmetic\", \"Returns an approximation of the median (50th percentile) as a scalar value.\", \"input\", \"method\"),\n  ),\n  $min: flex(\"comparison\", \"Returns the minimum value that results from applying an expression.\"),\n  $percentile: acc(\n    obj(\n      \"arithmetic\",\n      \"Returns an array of scalar values that correspond to specified percentile values.\",\n      \"input\",\n      \"p\",\n      \"method\",\n    ),\n  ),\n  $push: acc(single(\"array\", \"Returns an array of values that result from applying an expression.\")),\n  $stdDevPop: flex(\"arithmetic\", \"Calculates the population standard deviation of the input values.\"),\n  $stdDevSamp: flex(\"arithmetic\", \"Calculates the sample standard deviation of the input values.\"),\n  $sum: flex(\"arithmetic\", \"Returns a sum of numerical values, ignoring non-numeric values.\"),\n  $bottom: acc(\n    obj(\n      \"array\",\n      \"Returns the bottom element within a group according to the specified sort order.\",\n      \"output\",\n      \"sortBy\",\n    ),\n  ),\n  $bottomN: acc(\n    obj(\n      \"array\",\n      \"Returns an aggregation of the bottom n elements within a group, according to the specified sort order.\",\n      \"output\",\n      \"sortBy\",\n      \"n\",\n    ),\n  ),\n  $top: acc(\n    obj(\"array\", \"Returns the top element within a group according to the specified sort order.\", \"output\", \"sortBy\"),\n  ),\n  $topN: acc(\n    obj(\n      \"array\",\n      \"Returns an aggregation of the top n fields within a group, according to the specified sort order.\",\n      \"output\",\n      \"sortBy\",\n      \"n\",\n    ),\n  ),\n\n  // \u2500\u2500 Window (only valid inside $setWindowFields) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  $covariancePop: array(\"window\", \"Returns the population covariance of two numeric expressions.\"),\n  $covarianceSamp: array(\"window\", \"Returns the sample covariance of two numeric expressions.\"),\n  $denseRank: none(\n    \"window\",\n    \"Returns the document position (rank) within the partition. There are no gaps; ties receive the same rank.\",\n  ),\n  $derivative: obj(\"window\", \"Returns the average rate of change within the specified window.\", \"input\", \"unit\"),\n  $documentNumber: none(\n    \"window\",\n    \"Returns the position of a document in the $setWindowFields partition. Ties produce different adjacent numbers.\",\n  ),\n  $expMovingAvg: obj(\n    \"window\",\n    \"Returns the exponential moving average for the numeric expression.\",\n    \"input\",\n    \"N\",\n    \"alpha\",\n  ),\n  $integral: obj(\"window\", \"Returns the approximation of the area under a curve.\", \"input\", \"unit\"),\n  $linearFill: single(\n    \"window\",\n    \"Fills null and missing fields in a window using linear interpolation based on surrounding field values.\",\n  ),\n  $locf: single(\n    \"window\",\n    \"Last observation carried forward \u2014 sets null/missing fields in a window to the last non-null value.\",\n  ),\n  $rank: none(\"window\", \"Returns the document position (rank) within the $setWindowFields partition.\"),\n  $shift: obj(\n    \"window\",\n    \"Returns the value from an expression applied to a document in a specified position relative to the current document.\",\n    \"output\",\n    \"by\",\n    \"default\",\n  ),\n};\n\nexport function lookupOperator(name: string): OperatorDef | undefined {\n  // name already includes leading $\n  return OPERATORS[name];\n}\n", "import { lookupOperator } from \"./operators.ts\";\nimport { didYouMean } from \"./levenshtein.ts\";\nimport { SET_METHODS } from \"./ast.ts\";\nimport type {\n  BinaryOp,\n  Expr,\n  ArrayElement,\n  ObjectEntry,\n  CallArg,\n  SpreadElement,\n  KeyValueEntry,\n  MathMethod,\n  MathConstant,\n  ObjectMethod,\n  NumberStaticMethod,\n  TypeCastOp,\n  AssignExpr,\n  UpdateOp,\n  UpdateFilter,\n} from \"./ast.ts\";\n\nexport class CodegenError extends Error {\n  readonly pos: number;\n  constructor(message: string, pos: number = 0) {\n    super(message);\n    this.name = \"CodegenError\";\n    this.pos = pos;\n  }\n}\n\n/**\n * Throw a `CodegenError` flagged as a jsmql bug. Use for invariants the\n * parser is supposed to uphold \u2014 if a user ever sees one of these messages,\n * something has slipped past the parser's validation and we want them to\n * report it. Keeps the wording consistent across every internal-only throw\n * site so they're trivially greppable.\n */\nexport function internalError(detail: string, pos: number = 0): never {\n  throw new CodegenError(`jsmql internal error (please report to the jsmql maintainers): ${detail}`, pos);\n}\n\nexport class UnknownIdentifierError extends CodegenError {\n  identifier: string;\n  constructor(identifier: string, pos: number = 0) {\n    super(`Unknown identifier '${identifier}'. Did you mean '$.${identifier}'?`, pos);\n    this.name = \"UnknownIdentifierError\";\n    this.identifier = identifier;\n  }\n}\n\n// \u2500\u2500 Context \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type GenerateCtx = {\n  lambdaParams: ReadonlySet<string>;\n  reduceRemap?: ReadonlyMap<string, string>;\n  /**\n   * Pipeline-scoped `let` bindings in scope. Key is the user-facing name; value\n   * is the field-path string to read it back (e.g. `\"__jsmql.subtotal\"` \u2014 no\n   * leading `$`, that gets prepended at lookup sites). Threaded through\n   * pipeline lowering by `pipeline.ts`; ignored in expression-mode codegen.\n   */\n  pipelineLets?: ReadonlyMap<string, string>;\n  /**\n   * Names of lets that were dropped by an earlier scope-reshaping stage\n   * (`$group`, `$replaceRoot`, \u2026). Value is the stage that dropped them, used\n   * to produce a precise \"let X can't be read after $group\" error rather than\n   * the generic \"unknown identifier\" fallback.\n   */\n  droppedLets?: ReadonlyMap<string, string>;\n  /**\n   * Function-form parameter bindings in scope. Key is the destructured binding\n   * name; value is the raw JS value supplied at call time (already validated\n   * JSON-safe by `validateInterpolatable`). A `ParamRef` whose name lives here\n   * emits the value as an inline literal in the MQL output \u2014 the same shape\n   * the template-tag form produces from `${value}` interpolation. Bindings\n   * are *compile-time constants*, not document state, so unlike `pipelineLets`\n   * they cross sub-pipeline boundaries; `freshSubPipelineCtx` preserves them.\n   */\n  bindings?: ReadonlyMap<string, unknown>;\n  /**\n   * Static type of selected in-scope lambda bindings. Currently populated only\n   * by the `.reduce()` codegen when both `initialValue` and the lambda body\n   * are statically the same compound type \u2014 see the reduce case below. Read by\n   * the `IndexAccess` codegen to skip the runtime `$cond` on `$isArray` when\n   * the receiver is a `ParamRef` whose name is in this map. Keyed by the\n   * user-facing param name (pre-`reduceRemap`), so the lookup happens on the\n   * raw AST `ParamRef.name` before any MQL variable-name remap.\n   */\n  bindingTypes?: ReadonlyMap<string, \"object\" | \"array\">;\n  /**\n   * When true, suppress the auto-`$literal` wrap on `\"$...\"`-shaped string\n   * literals. Set by the `$literal(...)` operator codegen on the recursive\n   * call for its argument \u2014 the whole subtree is already inside a `$literal`\n   * envelope, so MongoDB will not interpret nested strings as field refs and\n   * a second wrap would produce a literal of a literal. Propagated through\n   * `extendCtx` so it survives lambda bodies and other ctx-modifying paths.\n   */\n  insideLiteral?: boolean;\n  /**\n   * When true, suppress the auto-`$literal` wrap on `\"$...\"`-shaped string\n   * literals because we're in a *field-path position*, not an expression. Set\n   * by `pipeline.ts` when lowering a `$unwind` body: `$unwind`'s path is a\n   * field path (`\"$items\"`), so the leading `$` is exactly what the user means\n   * \u2014 wrapping it in `$literal` would break the stage. Distinct from\n   * `insideLiteral` (which means \"already inside a `$literal` envelope\"); the\n   * effect on `literalSafeString` is the same, but the reason differs.\n   */\n  fieldPathString?: boolean;\n  /**\n   * Accumulator context \u2014 set by `pipeline.ts` when descending into a `$group`\n   * field-value body (other than `_id`) or a `$setWindowFields.output[<key>]`\n   * slot. Used by the operator-call codegen to gate operators that only make\n   * sense inside one of these contexts:\n   *   - `\"group\"`: accumulator-only operators ($addToSet, $push, $bottom*, etc.)\n   *     are allowed; window-only operators ($rank, $denseRank, etc.) are NOT.\n   *   - `\"window-output\"`: BOTH accumulator-only AND window-only operators are\n   *     allowed.\n   *   - unset / undefined: neither \u2014 outside any aggregation accumulator scope.\n   */\n  accumulatorContext?: \"group\" | \"window-output\";\n};\n\nconst EMPTY_CTX: GenerateCtx = { lambdaParams: new Set() };\n\nfunction extendCtx(ctx: GenerateCtx, params: string[]): GenerateCtx {\n  return {\n    lambdaParams: new Set([...ctx.lambdaParams, ...params]),\n    reduceRemap: ctx.reduceRemap,\n    pipelineLets: ctx.pipelineLets,\n    droppedLets: ctx.droppedLets,\n    bindings: ctx.bindings,\n    bindingTypes: ctx.bindingTypes,\n    insideLiteral: ctx.insideLiteral,\n    fieldPathString: ctx.fieldPathString,\n    accumulatorContext: ctx.accumulatorContext,\n  };\n}\n\n/** Add a new pipeline let to the context. Returns a fresh ctx; never mutates. */\nexport function extendCtxLets(ctx: GenerateCtx, name: string, fieldPath: string): GenerateCtx {\n  const next = new Map(ctx.pipelineLets ?? []);\n  next.set(name, fieldPath);\n  return { ...ctx, pipelineLets: next };\n}\n\n/** Drop all pipeline lets, moving them to `droppedLets` with the stage name. */\nexport function clearCtxLets(ctx: GenerateCtx, droppedByStage: string): GenerateCtx {\n  if (!ctx.pipelineLets || ctx.pipelineLets.size === 0) return ctx;\n  const dropped = new Map(ctx.droppedLets ?? []);\n  for (const name of ctx.pipelineLets.keys()) dropped.set(name, droppedByStage);\n  return { ...ctx, pipelineLets: new Map(), droppedLets: dropped };\n}\n\n/** Public access for pipeline.ts to read the let-bindings count. */\nexport function ctxHasLets(ctx: GenerateCtx): boolean {\n  return (ctx.pipelineLets?.size ?? 0) > 0;\n}\n\n/**\n * Construct a fresh ctx for sub-pipeline lowering. Outer `let` bindings do NOT\n * cross \u2014 they're per-document state and the sub-pipeline starts against a\n * different document (e.g. `$lookup.pipeline` runs against the foreign\n * collection). Function-form `bindings` DO cross: they are compile-time\n * constants, not document state, and inlining them inside a sub-pipeline is\n * the same shape as the user writing the literal there directly.\n */\nexport function freshSubPipelineCtx(outer: GenerateCtx): GenerateCtx {\n  return { lambdaParams: new Set(), bindings: outer.bindings };\n}\n\n/**\n * Construct a sub-pipeline ctx that PRESERVES outer pipeline lets \u2014 used by\n * `$facet` branches. Unlike `$lookup.pipeline` / `$unionWith.pipeline`\n * (which operate on a different document set), every facet branch operates\n * on the SAME input docs that arrived at the outer pipeline's $facet stage.\n * Those docs still carry the `__jsmql.<name>` fields the outer lets\n * materialised into, so `$__jsmql.<name>` references inside the branch\n * resolve correctly.\n */\nexport function freshFacetCtx(outer: GenerateCtx): GenerateCtx {\n  return { lambdaParams: new Set(), bindings: outer.bindings, pipelineLets: outer.pipelineLets };\n}\n\n/** Return a fresh ctx with the given function-form parameter bindings applied. */\nexport function withBindings(ctx: GenerateCtx, bindings: ReadonlyMap<string, unknown>): GenerateCtx {\n  return { ...ctx, bindings };\n}\n\n/** Public re-export of EMPTY_CTX for pipeline.ts. */\nexport { EMPTY_CTX };\n\n// \u2500\u2500 String-producing helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n// Operators whose return type is always a string \u2014 used for string-context + inference.\nconst STRING_OUTPUT_OPS = new Set([\n  \"$toLower\",\n  \"$toUpper\",\n  \"$trim\",\n  \"$ltrim\",\n  \"$rtrim\",\n  \"$concat\",\n  \"$substrCP\",\n  \"$substrBytes\",\n  \"$substr\",\n  \"$replaceOne\",\n  \"$replaceAll\",\n  \"$dateToString\",\n  \"$type\",\n  \"$strcasecmp\",\n  \"$toString\",\n]);\n\n// \u2500\u2500 JS-method metadata registry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Single source of truth for every JS method jsmql recognises. The lowering for\n// each method still lives in its `case` in generateMethodCall (the dispatch is\n// the switch); this table holds the *metadata* that several inference passes\n// read \u2014 return type and optional-chaining receiver type \u2014 plus the full name\n// list that powers \"did you mean?\" suggestions. Adding a method is one entry\n// here (for its inference behaviour) plus its `case`, instead of editing up to\n// three separate Sets scattered across the file.\n//\n//   returns:  the method's result type, when invariant \u2014 feeds isStringProducing\n//             / isArrayProducing / isProvablyBool. Omitted when the result type\n//             depends on the receiver/args (e.g. `.slice`, `.concat`, `.at`).\n//   optional: the receiver's type, picking the `$ifNull` neutral when a `?.`\n//             chain feeds the receiver \u2014 \"string\" \u2192 \"\", \"array\" \u2192 [], \"either\" \u2192\n//             runtime/branch-aware (see neutralForMethod). Omitted for methods\n//             whose underlying operator handles null cleanly (date/set/regex).\ntype MethodReturn = \"string\" | \"array\" | \"bool\";\ntype MethodOptional = \"string\" | \"array\" | \"either\";\ntype MethodMeta = { returns?: MethodReturn; optional?: MethodOptional };\n\nconst METHODS: Record<string, MethodMeta> = {\n  // \u2500\u2500 String \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  trim: { returns: \"string\", optional: \"string\" },\n  trimStart: { returns: \"string\", optional: \"string\" },\n  trimLeft: { returns: \"string\", optional: \"string\" },\n  trimEnd: { returns: \"string\", optional: \"string\" },\n  trimRight: { returns: \"string\", optional: \"string\" },\n  toLowerCase: { returns: \"string\", optional: \"string\" },\n  toUpperCase: { returns: \"string\", optional: \"string\" },\n  substr: { returns: \"string\", optional: \"string\" },\n  substring: { returns: \"string\", optional: \"string\" },\n  charAt: { returns: \"string\", optional: \"string\" },\n  split: { returns: \"array\", optional: \"string\" }, // returns an array, but the receiver is a string\n  startsWith: { returns: \"bool\", optional: \"string\" },\n  endsWith: { returns: \"bool\", optional: \"string\" },\n  replace: { returns: \"string\", optional: \"string\" },\n  replaceAll: { returns: \"string\", optional: \"string\" },\n  match: { optional: \"string\" },\n  matchAll: { optional: \"string\" },\n  search: { optional: \"string\" },\n  padStart: { returns: \"string\", optional: \"string\" },\n  padEnd: { returns: \"string\", optional: \"string\" },\n  repeat: { returns: \"string\", optional: \"string\" },\n  indexOf: { optional: \"either\" },\n  includes: { returns: \"bool\", optional: \"either\" },\n  // \u2500\u2500 Array \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  at: { optional: \"array\" },\n  slice: { optional: \"either\" },\n  concat: { optional: \"either\" },\n  reverse: { returns: \"array\", optional: \"array\" }, // throws in expression position; metadata used by the statement-position rewrite\n  toReversed: { returns: \"array\", optional: \"array\" },\n  toSorted: { returns: \"array\", optional: \"array\" },\n  toSpliced: { returns: \"array\" },\n  with: { returns: \"array\" },\n  flat: { returns: \"array\", optional: \"array\" },\n  flatMap: { returns: \"array\", optional: \"array\" },\n  map: { returns: \"array\", optional: \"array\" },\n  filter: { returns: \"array\", optional: \"array\" },\n  find: { optional: \"array\" },\n  findIndex: {},\n  findLast: { optional: \"array\" },\n  findLastIndex: { optional: \"array\" },\n  lastIndexOf: {},\n  some: { returns: \"bool\", optional: \"array\" },\n  every: { returns: \"bool\", optional: \"array\" },\n  reduce: { optional: \"array\" },\n  reduceRight: {},\n  join: { returns: \"string\", optional: \"array\" }, // returns a string, but the receiver is an array\n  toString: {},\n  // \u2500\u2500 Mutators (shimmed with tailored errors that point at immutable variants) \u2500\n  sort: {},\n  splice: {},\n  push: {},\n  pop: {},\n  shift: {},\n  unshift: {},\n  fill: {},\n  copyWithin: {},\n  // \u2500\u2500 Iterator / void / locale (shimmed with tailored errors) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  forEach: {},\n  entries: {},\n  keys: {},\n  values: {},\n  toLocaleString: {},\n  // \u2500\u2500 Date \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  getFullYear: {},\n  getMonth: {},\n  getDate: {},\n  getDay: {},\n  getHours: {},\n  getMinutes: {},\n  getSeconds: {},\n  getMilliseconds: {},\n  getTime: {},\n  toISOString: { returns: \"string\" },\n  // \u2500\u2500 Set (intercepted before generateMethodCall when the receiver is a NewSet,\n  //    but listed so a typo on a non-NewSet receiver still surfaces a suggestion) \u2500\n  intersection: {},\n  union: {},\n  difference: {},\n  isSubsetOf: {},\n  isSupersetOf: {},\n  // \u2500\u2500 Regex (intercepted on RegexLiteral receivers; same rationale) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  test: {},\n  exec: {},\n};\n\nfunction methodsWhere(pred: (m: MethodMeta) => boolean): ReadonlySet<string> {\n  return new Set(Object.keys(METHODS).filter((name) => pred(METHODS[name])));\n}\n\n// Method names that always return a string / array / boolean \u2014 derived from METHODS.\nconst STRING_RETURNING_METHODS = methodsWhere((m) => m.returns === \"string\");\n\n// \u2500\u2500 Array-producing helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n// Operators whose return type is always an array\nconst ARRAY_OUTPUT_OPS = new Set([\n  \"$split\",\n  \"$range\",\n  \"$reverseArray\",\n  \"$slice\",\n  \"$map\",\n  \"$filter\",\n  \"$concatArrays\",\n  \"$setUnion\",\n  \"$setIntersection\",\n  \"$setDifference\",\n  \"$zip\",\n  \"$objectToArray\",\n]);\n\n// Method names that always return an array \u2014 derived from METHODS.\nconst ARRAY_RETURNING_METHODS = methodsWhere((m) => m.returns === \"array\");\n\nfunction isArrayProducing(expr: Expr): boolean {\n  switch (expr.type) {\n    case \"ArrayLiteral\":\n      return true;\n    case \"OperatorCall\":\n      return ARRAY_OUTPUT_OPS.has(expr.name);\n    case \"MethodCall\":\n      // `.slice` preserves receiver type \u2014 array\u2192array, string\u2192string.\n      if (expr.method === \"slice\") return isArrayProducing(expr.object);\n      return ARRAY_RETURNING_METHODS.has(expr.method);\n    case \"ObjectCall\":\n      return expr.method === \"entries\" || expr.method === \"keys\" || expr.method === \"values\";\n    default:\n      return false;\n  }\n}\n\nfunction isObjectProducing(expr: Expr): boolean {\n  return expr.type === \"ObjectLiteral\";\n}\n\nfunction isStringProducing(expr: Expr): boolean {\n  switch (expr.type) {\n    case \"StringLiteral\":\n      return true;\n    case \"TemplateLiteral\":\n      return true;\n    case \"OperatorCall\":\n      return STRING_OUTPUT_OPS.has(expr.name);\n    case \"MethodCall\":\n      // `.slice` preserves receiver type \u2014 array\u2192array, string\u2192string.\n      if (expr.method === \"slice\") return isStringProducing(expr.object);\n      return STRING_RETURNING_METHODS.has(expr.method);\n    case \"TypeCast\":\n      return expr.cast === \"String\";\n    case \"TypeofExpr\":\n      return true;\n    case \"BinaryExpr\":\n      if (expr.op === \"+\") {\n        const chain: Expr[] = [];\n        collectExprChain(\"+\", expr, chain);\n        return chain.some((e) => isStringProducing(e));\n      }\n      return false;\n    default:\n      return false;\n  }\n}\n\n// \u2500\u2500 JS truthy/falsy semantics \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// JavaScript treats `false`, `null`, `undefined`, `0`, `\"\"`, and `NaN` as\n// falsy; everything else (including `[]` and `{}`) is truthy. MongoDB's\n// $cond/$and/$or/$not/$toBool use a different rule (e.g. `\"\"` is truthy in\n// MQL). To make `&&`, `||`, `!`, `?:`, `Boolean()`, and predicate-method\n// bodies match the JS semantics users expect, we wrap operands in `jsBool`.\n//\n// NaN: detecting NaN in MongoDB is expensive (its $eq treats NaN==NaN as\n// true, so `$ne:[x,x]` does not work). NaN values are vanishingly rare in\n// MongoDB collections, so we accept this divergence and document it.\n\n// Operators whose return type is always a boolean \u2014 used to elide the jsBool\n// wrap when an operand is already a boolean.\nconst BOOL_OUTPUT_OPS = new Set([\n  \"$eq\",\n  \"$ne\",\n  \"$gt\",\n  \"$gte\",\n  \"$lt\",\n  \"$lte\",\n  \"$and\",\n  \"$or\",\n  \"$not\",\n  \"$in\",\n  \"$regexMatch\",\n  \"$isNumber\",\n  \"$isArray\",\n  \"$allElementsTrue\",\n  \"$anyElementTrue\",\n  \"$setEquals\",\n  \"$setIsSubset\",\n]);\n\n// Method names whose codegen always emits a boolean \u2014 derived from METHODS.\nconst BOOL_RETURNING_METHODS = methodsWhere((m) => m.returns === \"bool\");\n\n/** True if the AST node always compiles to an MQL expression that evaluates\n *  to a boolean. When true we skip the jsBool wrap. */\nfunction isProvablyBool(expr: Expr): boolean {\n  switch (expr.type) {\n    case \"BooleanLiteral\":\n      return true;\n    case \"UnaryExpr\":\n      return expr.op === \"!\";\n    case \"BinaryExpr\":\n      switch (expr.op) {\n        case \"==\":\n        case \"===\":\n        case \"!=\":\n        case \"!==\":\n        case \"<\":\n        case \"<=\":\n        case \">\":\n        case \">=\":\n        case \"in\":\n          return true;\n        case \"&&\":\n        case \"||\":\n          // JS `&&`/`||` are operand-preserving, so they're bool only when\n          // every operand is bool. Recurse \u2014 this matches the chain-level\n          // optimization in `generateLogical` which emits `$and`/`$or`\n          // (a bool) for all-bool chains.\n          return isProvablyBool(expr.left) && isProvablyBool(expr.right);\n        default:\n          return false;\n      }\n    case \"TypeCast\":\n      return expr.cast === \"Boolean\";\n    case \"OperatorCall\":\n      return BOOL_OUTPUT_OPS.has(expr.name);\n    case \"MethodCall\":\n      return BOOL_RETURNING_METHODS.has(expr.method);\n    default:\n      return false;\n  }\n}\n\n/** Wrap an already-generated MQL expression in a JS-truthy check.\n *  Returns true iff `value` is truthy under JS rules (false, null, missing,\n *  0, \"\" \u2192 false; everything else \u2192 true; NaN treated as truthy \u2014 see note). */\nfunction jsBool(value: unknown): unknown {\n  return {\n    $and: [\n      { $ne: [value, null] }, // catches null AND missing \u2014 MongoDB treats them equal in $ne\n      { $ne: [value, false] },\n      { $ne: [value, \"\"] },\n      { $ne: [value, 0] },\n    ],\n  };\n}\n\n/** jsBool around a generated value, but elide if the source AST is already\n *  provably boolean. The AST is needed to do the elision check; the generated\n *  value is what gets emitted. Pass them both for the common case where\n *  callers have already invoked _generate(). */\nfunction jsBoolIfNeeded(srcExpr: Expr, generated: unknown): unknown {\n  return isProvablyBool(srcExpr) ? generated : jsBool(generated);\n}\n\n/** True if `expr` resolves to a stable field/param/path (no computation,\n *  no side-effects, free to reference twice). Used by `&&`/`||` to decide\n *  whether the operand-preserving codegen needs a `$let` to bind once. */\nfunction isPureRef(expr: Expr, ctx: GenerateCtx): boolean {\n  return asFieldPath(expr, ctx) !== null;\n}\n\n/** Pick a $let binding name that doesn't shadow any in-scope lambda param. */\nfunction gensymInScope(ctx: GenerateCtx, base: string): string {\n  if (!ctx.lambdaParams.has(base)) return base;\n  for (let i = 2; ; i++) {\n    const name = `${base}${i}`;\n    if (!ctx.lambdaParams.has(name)) return name;\n  }\n}\n\n/**\n * Clamp a string-index AST node to non-negative, matching JS `.substring`\n * semantics where negative arguments are treated as 0. Folds at compile time\n * when the node is a literal number (or unary-minus of one); otherwise wraps\n * the generated value in `$max:[0, \u2026]` so the runtime sees a non-negative\n * index.\n */\nfunction clampNonNegativeIndex(node: Expr, ctx: GenerateCtx): unknown {\n  if (node.type === \"NumberLiteral\") return Math.max(0, node.value);\n  if (node.type === \"UnaryExpr\" && node.op === \"-\" && node.operand.type === \"NumberLiteral\") {\n    return Math.max(0, -node.operand.value);\n  }\n  return { $max: [0, _generate(node, ctx)] };\n}\n\n/** Clamp a derived length value to non-negative, folding when known. */\nfunction clampNonNegativeLength(value: unknown): unknown {\n  if (typeof value === \"number\") return Math.max(0, value);\n  return { $max: [0, value] };\n}\n\n/** Subtract `b` from `a`, folding when both operands are numeric literals. */\nfunction foldedSubtract(a: unknown, b: unknown): unknown {\n  if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n  return { $subtract: [a, b] };\n}\n\n/**\n * Normalise a JS-style `.slice` index against a string length. JS treats\n * negative indices as `len + idx`; MQL `$substrCP` rejects negatives. Folds\n * literal negatives into `$strLenCP - n` at compile time; non-literals expand\n * to a `$cond` that picks the form at runtime.\n *\n * `genObj` is reused for `$strLenCP` rather than re-generating from the\n * source AST, so callers should pass the same generated value they use in\n * the surrounding `$substrCP` call.\n */\nfunction normaliseSliceIndex(node: Expr, ctx: GenerateCtx, genObj: unknown): unknown {\n  if (node.type === \"NumberLiteral\") {\n    if (node.value >= 0) return node.value;\n    return foldedSubtract({ $strLenCP: genObj }, -node.value);\n  }\n  if (node.type === \"UnaryExpr\" && node.op === \"-\" && node.operand.type === \"NumberLiteral\") {\n    return foldedSubtract({ $strLenCP: genObj }, node.operand.value);\n  }\n  const gen = _generate(node, ctx);\n  return { $cond: [{ $lt: [gen, 0] }, { $add: [gen, { $strLenCP: genObj }] }, gen] };\n}\n\n/** Lower `.slice` on a known-array (or fallback) receiver to MQL `$slice`. */\nfunction sliceArray(genObj: unknown, exprArgs: Expr[], ctx: GenerateCtx): unknown {\n  if (exprArgs.length === 0) return genObj;\n  if (exprArgs.length === 1) return { $slice: [genObj, _generate(exprArgs[0], ctx)] };\n  return { $slice: [genObj, _generate(exprArgs[0], ctx), _generate(exprArgs[1], ctx)] };\n}\n\n/** Lower `.slice` on a known-string receiver to MQL `$substrCP`. */\nfunction sliceString(genObj: unknown, exprArgs: Expr[], ctx: GenerateCtx): unknown {\n  if (exprArgs.length === 0) return genObj;\n  const start = normaliseSliceIndex(exprArgs[0], ctx, genObj);\n  if (exprArgs.length === 1) {\n    // For 1-arg `.slice(-n)` on a string, the length is exactly `n` (JS\n    // returns the last n characters). Fold that case so the output isn't\n    // a noisy `strLen - (strLen - n)`.\n    const negativeLiteral = negativeLiteralValue(exprArgs[0]);\n    if (negativeLiteral !== null) return { $substrCP: [genObj, start, negativeLiteral] };\n    return { $substrCP: [genObj, start, foldedSubtract({ $strLenCP: genObj }, start)] };\n  }\n  const end = normaliseSliceIndex(exprArgs[1], ctx, genObj);\n  return { $substrCP: [genObj, start, clampNonNegativeLength(foldedSubtract(end, start))] };\n}\n\n/** Return the absolute value of a negative numeric literal AST node, else null. */\nfunction negativeLiteralValue(node: Expr): number | null {\n  if (node.type === \"NumberLiteral\" && node.value < 0) return -node.value;\n  if (node.type === \"UnaryExpr\" && node.op === \"-\" && node.operand.type === \"NumberLiteral\" && node.operand.value > 0) {\n    return node.operand.value;\n  }\n  return null;\n}\n\n/**\n * Emit a string literal in a value position, auto-wrapping in `$literal` when\n * the value would be misread by MongoDB as a field reference / system variable.\n *\n * In MongoDB aggregation expression context, any string value that starts with\n * `$` is interpreted at query time \u2014 `\"$foo\"` reads field `foo`, `\"$$NOW\"` is\n * the system variable. A user who writes the string literal `\"$foo\"` in jsmql\n * source means the literal four-character string, not field access (they'd\n * write `$.foo` for that). Wrap in `$literal` so the runtime keeps it intact.\n *\n * Suppressed when `ctx.insideLiteral` is set \u2014 we're already inside a\n * `$literal(...)` envelope, MongoDB will not re-evaluate this subtree, and a\n * second wrap would produce a literal-of-a-literal.\n */\nfunction literalSafeString(value: string, ctx: GenerateCtx): unknown {\n  if (ctx.insideLiteral || ctx.fieldPathString) return value;\n  if (value.length > 0 && value.charCodeAt(0) === 36 /* $ */) {\n    return { $literal: value };\n  }\n  return value;\n}\n\n/**\n * Apply the same `$literal` safety net to a `jsmql.compile`/template-tag bound\n * value as we do to user-written string literals: any `\"$...\"`-shaped string,\n * at any nesting depth, gets wrapped so MongoDB doesn't read it as a field ref\n * at runtime. Plain objects and arrays recurse; primitives pass through.\n *\n * `validateInterpolatable` has already rejected functions, symbols, BigInt,\n * non-finite numbers, and circular references, so this walker only needs to\n * handle JSON-shaped data \u2014 and opaque BSON instances (Date, RegExp,\n * Uint8Array, ObjectId), which are passed through unchanged because they're\n * the very values MongoDB's driver expects in-situ; walking them with\n * `Object.entries` would silently strip them to `{}`.\n */\nfunction safeBoundValue(value: unknown, ctx: GenerateCtx): unknown {\n  if (ctx.insideLiteral) return value;\n  if (typeof value === \"string\") return literalSafeString(value, ctx);\n  if (isOpaqueBsonValue(value)) return value;\n  if (Array.isArray(value)) return value.map((v) => safeBoundValue(v, ctx));\n  if (value !== null && typeof value === \"object\") {\n    const out: Record<string, unknown> = {};\n    for (const [k, v] of Object.entries(value)) {\n      out[k] = safeBoundValue(v, ctx);\n    }\n    return out;\n  }\n  return value;\n}\n\n/**\n * BSON instance values that the MongoDB driver consumes in-situ (i.e. the\n * driver expects the actual JS object, not a JSON-shaped surrogate). They\n * have no fidelity-preserving JSON representation: `JSON.stringify` returns\n * `\"{}\"` for `RegExp` and `Uint8Array`, an ISO string for `Date` (which\n * compares as a string in BSON, not a date), and `{}` for ObjectId.\n *\n * ObjectId is detected by `_bsontype` because importing the MongoDB driver\n * would add a hard dependency the library deliberately avoids; the BSON\n * library tags instances with `\"ObjectID\"` (older versions) or `\"ObjectId\"`\n * (newer versions). Accept both.\n */\nexport function isOpaqueBsonValue(value: unknown): boolean {\n  if (value instanceof Date) return true;\n  if (value instanceof RegExp) return true;\n  if (value instanceof Uint8Array) return true;\n  if (typeof value === \"object\" && value !== null) {\n    const tag = (value as { _bsontype?: unknown })._bsontype;\n    if (tag === \"ObjectID\" || tag === \"ObjectId\") return true;\n  }\n  return false;\n}\n\n// \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function generate(expr: Expr): unknown {\n  return _generate(expr, EMPTY_CTX);\n}\n\n/** Generate an expression with an explicit context (e.g. pipeline-let bindings). */\nexport function generateWithCtx(expr: Expr, ctx: GenerateCtx): unknown {\n  return _generate(expr, ctx);\n}\n\n// \u2500\u2500 Core generator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction _generate(expr: Expr, ctx: GenerateCtx): unknown {\n  return _generateBody(expr, ctx);\n}\n\nfunction _generateBody(expr: Expr, ctx: GenerateCtx): unknown {\n  // Defensive: parseGrouped may surface an AssignExpr through this path when\n  // it sees `($.x = expr)` \u2014 a parenthesized assignment. AssignExpr is not in\n  // the Expr union, but the cast in parseGrouped lets it flow here. Reject\n  // with a clear message so users debugging `1 + ($.a = 5)` see what's wrong.\n  const dynType = (expr as unknown as { type: string }).type;\n  if (dynType === \"AssignExpr\" || dynType === \"DeleteStmt\") {\n    throw new CodegenError(\n      `${dynType === \"AssignExpr\" ? \"Assignment\" : \"delete\"} is a statement, not a value. ` +\n        `It is only valid at the top level or as a pipeline-array element.`,\n      expr.pos,\n    );\n  }\n  if (dynType === \"LetDecl\") {\n    throw new CodegenError(\n      \"`let` is a pipeline statement, not a value. \" + \"It is only valid at the top level of a pipeline.\",\n      expr.pos,\n    );\n  }\n  switch (expr.type) {\n    case \"NumberLiteral\":\n      return expr.value;\n    case \"BigIntLiteral\":\n      return { $toLong: expr.value };\n    case \"StringLiteral\":\n      return literalSafeString(expr.value, ctx);\n    case \"BooleanLiteral\":\n      return expr.value;\n    case \"NullLiteral\":\n      return null;\n    case \"UndefinedLiteral\":\n      // MongoDB's aggregation expression language has no way to distinguish\n      // \"missing field\" from \"field present with null value\" \u2014 `$eq` against\n      // missing returns true for both. `undefined` only carries non-redundant\n      // meaning in `$match` position (where it lowers to `$exists`); in any\n      // expression position it's ambiguous, so we surface an actionable error\n      // rather than silently lowering to `null`.\n      throw new CodegenError(\n        `'undefined' is only meaningful in '$match' position (where it lowers to '$exists'). ` +\n          `In aggregation expressions, use 'null' for the present-but-null case, or move the comparison into a '$match' stage.`,\n        expr.pos,\n      );\n    case \"FieldRef\":\n      // Bare `$` (empty path) is the current document \u2014 MQL spells it `$$ROOT`.\n      // Nested paths (`$.a.b`) lower verbatim to `\"$a.b\"`.\n      return expr.path === \"\" ? \"$$ROOT\" : `$${expr.path}`;\n\n    case \"CollectionRef\":\n      // `$$.push(...)` is materialised into `$unionWith` stages,\n      // `$$.filter(...)` inside `$ = { ... }` is materialised into a `$facet`\n      // stage, and `$$ = <expr>` is materialised into `$match` (narrow) or\n      // `$limit: 0` + `$unionWith` (source switch) \u2014 all by `pipeline.ts`\n      // *before* codegen sees the surrounding expression. A bare\n      // `CollectionRef` reaching this case is a use outside those supported\n      // shapes \u2014 either `$$` was referenced as a value (in arithmetic, a\n      // Filter, an inline expression) or the statement-shaped form appeared\n      // in a non-statement position (on a RHS, inside another expression, etc.).\n      throw new CodegenError(\n        `'$$' (current collection) is statement-only and supports '.push(...)', '.filter(...)' in the facet pattern, and '$$ = <expr>' as a top-level assignment. ` +\n          `Write \\`$$.push({...})\\`, \\`$$.push(...$$$.<coll>[.filter(pred)])\\`, or \\`$$.push($$$.<coll>.find(pred))\\` ` +\n          `as a top-level Pipeline statement to append documents (lowers to '$unionWith'), ` +\n          `\\`$ = { key1: $$.filter(p1), key2: $$.filter(p2), ... }\\` to build a '$facet' stage, ` +\n          `or \\`$$ = $$.filter(<pred>)\\` / \\`$$ = $$$.<coll>.filter(<pred>)\\` to replace the current stream. ` +\n          `As the first stage it also accepts a collection-scoped diagnostic \u2014 \\`$$.indexStats()\\`, \\`$$.collStats({...})\\`, \\`$$.planCacheStats()\\`, \\`$$.listSearchIndexes({...})\\`. ` +\n          `Bare '$$' has no value, and these statement shapes cannot appear on a RHS or inside another expression.`,\n        expr.pos,\n      );\n    case \"DatabaseRef\":\n      // The two supported uses of `$$$` are both materialised by `pipeline.ts`\n      // *before* codegen sees the surrounding expression:\n      //   - `$$$.<coll>.find/filter(pred)` \u2192 `$lookup` stage (read).\n      //   - `$$$.<coll> = <RHS>`            \u2192 `$out` stage (write).\n      // Reaching this case means neither matched: the user wrote `$$$.<coll>`\n      // as a bare value, used the chain in an expression-only position (a\n      // Filter, `jsmql.expr`, an arithmetic operand), or used a method other\n      // than `.find/.filter` that the pre-materialisation walker didn't\n      // recognise.\n      throw new CodegenError(\n        `'$$$.<coll>' must be either followed by .find(pred) / .filter(pred) and consumed as a value (a $lookup read), ` +\n          `or assigned to as a destination ('$$$.<coll> = $$' \u2192 $out write). ` +\n          `Bare '$$$' reference is not a value, and these sugars are only valid in Pipeline mode (use \\`;\\`-separated statements or jsmql.pipeline()). ` +\n          `(System diagnostics aren't database-scoped: collection ones are on '$$', server/cluster ones on '$$$$'.)`,\n        expr.pos,\n      );\n    case \"ClusterRef\":\n      // Like DatabaseRef: the two supported uses of `$$$$.<db>.<coll>` are\n      // `.find/.filter(pred)` (cross-db lookup) and `= <RHS>` (cross-db $out).\n      // Both are materialised pre-codegen. Reaching this case means a use\n      // outside those shapes (bare reference, expression-only position,\n      // wrong depth, dynamic db/coll names, etc.).\n      throw new CodegenError(\n        `'$$$$.<db>.<coll>' must be either followed by .find(pred) / .filter(pred) and consumed as a value (a cross-database $lookup), ` +\n          `or assigned to as a destination ('$$$$.<db>.<coll> = $$' \u2192 cross-database $out). A direct call on '$$$$' is a server/cluster-scoped diagnostic source stage ` +\n          `(\\`$$$$.currentOp({...})\\`, \\`$$$$.listSessions({...})\\`, \\`$$$$.listLocalSessions({...})\\`, \\`$$$$.listSampledQueries({...})\\`, \\`$$$$.shardedDataDistribution()\\`) as the first Pipeline stage. ` +\n          `Bare '$$$$' reference is not a value, and these sugars are only valid in Pipeline mode (use \\`;\\`-separated statements or jsmql.pipeline()).`,\n        expr.pos,\n      );\n\n    case \"ArrayLiteral\":\n      return generateArrayLiteral(expr.elements, ctx, expr.pos);\n\n    case \"ObjectLiteral\":\n      return generateObjectLiteral(expr.entries, ctx, expr.pos);\n\n    case \"TemplateLiteral\":\n      return generateTemplateLiteral(expr.quasis, expr.expressions, ctx);\n\n    case \"OperatorCall\":\n      return generateOperatorCall(expr.name, expr.style, expr.args, ctx, expr.pos);\n\n    case \"BinaryExpr\":\n      return generateBinaryExpr(expr.op, expr.left, expr.right, ctx, expr.pos);\n\n    case \"UnaryExpr\":\n      return generateUnaryExpr(expr.op, expr.operand, ctx, expr.pos);\n\n    case \"TernaryExpr\":\n      return {\n        $cond: [\n          jsBoolIfNeeded(expr.condition, _generate(expr.condition, ctx)),\n          _generate(expr.consequent, ctx),\n          _generate(expr.alternate, ctx),\n        ],\n      };\n\n    case \"IndexAccess\": {\n      // `obj[idx]` and `obj?.[idx]` produce the same AST shape; only the\n      // `optional` flag distinguishes them. Type-aware dispatch:\n      //   known array (structural OR binding-typed)  \u2192 $arrayElemAt\n      //   known object (binding-typed only)          \u2192 $getField\n      //   unknown                                    \u2192 runtime $cond between the two\n      // Binding-typed = the receiver is a `ParamRef` whose name lives in\n      // `ctx.bindingTypes` (populated today by `.reduce()` when initialValue\n      // and body agree on a compound type). The optional-chain `$ifNull`\n      // fallback matches the consumer: `[]` for array, `{}` for object so a\n      // missing path doesn't poison `$getField` with an array.\n      // Bracket access is *raw* data access \u2014 no compiler interpretation of the\n      // key. Unlike dot `.length` (which folds to the string-or-array length\n      // operator), `[\"length\"]` just reads a property called \"length\". This\n      // makes brackets the deliberate escape hatch: whatever the user spells in\n      // the brackets is the property they get.\n      //\n      // `$[\"any.field\"]` \u2014 a string-literal key on the bare root document \u2014 is a\n      // plain field reference: the root is never an array, so the `$arrayElemAt`\n      // branch below would be dead, and this lets users reach a field whose name\n      // isn't a bare identifier (a dot, dash, space, \u2026) \u2014 e.g.\n      // `$[\"cart.field.length\"]` \u2192 `\"$cart.field.length\"`.\n      if (expr.index.type === \"StringLiteral\" && expr.object.type === \"FieldRef\" && expr.object.path === \"\") {\n        return `$${expr.index.value}`;\n      }\n      const rawObj = _generate(expr.object, ctx);\n      const idx = _generate(expr.index, ctx);\n      const optional = expr.optional || chainHasOptional(expr.object);\n      const known: \"object\" | \"array\" | undefined = isArrayProducing(expr.object)\n        ? \"array\"\n        : expr.object.type === \"ParamRef\"\n          ? ctx.bindingTypes?.get(expr.object.name)\n          : undefined;\n      if (known === \"array\") {\n        const obj = optional ? wrapIfNull(rawObj, []) : rawObj;\n        return { $arrayElemAt: [obj, idx] };\n      }\n      if (known === \"object\") {\n        const obj = optional ? wrapIfNull(rawObj, {}) : rawObj;\n        return { $getField: { field: idx, input: obj } };\n      }\n      const obj = optional ? wrapIfNull(rawObj, []) : rawObj;\n      return { $cond: [{ $isArray: obj }, { $arrayElemAt: [obj, idx] }, { $getField: { field: idx, input: obj } }] };\n    }\n\n    case \"RegexLiteral\":\n      // Method dispatch (e.g. `.match(/foo/)`, `/foo/.test(s)`) handles regex\n      // arguments and receivers directly, reading pattern + flags from the AST\n      // node before recursion. If we land here, the regex showed up in some\n      // other position (binary operand, ternary branch, $op argument value)\n      // where MQL has no concept of a regex value \u2014 silently returning the\n      // pattern string would lose the flags and surprise the user.\n      throw new CodegenError(\n        `Regex literals are only valid as arguments to .match(), .test(), .exec(), .matchAll(), and .search(). To pass a regex pattern as a string, use a string literal instead.`,\n        expr.pos,\n      );\n\n    case \"ParamRef\": {\n      // Resolution order (innermost wins):\n      //   1. `.reduce()` parameter remap (renamed to MQL's fixed $$value/$$this)\n      //   2. lambda parameter \u2014 emit `$$name`\n      //   3. pipeline `let` binding \u2014 emit `$<fieldPath>` (document field)\n      //   4. function-form parameter binding \u2014 emit the inlined literal value\n      //   5. dropped let \u2014 precise post-reshape error\n      //   6. otherwise \u2014 unknown identifier\n      // (3) and (4) are name-disjoint by construction (pipeline.ts rejects a\n      //  `let` that shadows a function-form binding), so their relative order\n      //  affects only the error path, not correctness for valid programs.\n      if (ctx.reduceRemap?.has(expr.name)) {\n        return `$$${ctx.reduceRemap.get(expr.name)!}`;\n      }\n      if (ctx.lambdaParams.has(expr.name)) {\n        return `$$${expr.name}`;\n      }\n      const letPath = ctx.pipelineLets?.get(expr.name);\n      if (letPath !== undefined) {\n        return `$${letPath}`;\n      }\n      if (ctx.bindings?.has(expr.name)) {\n        return safeBoundValue(ctx.bindings.get(expr.name), ctx);\n      }\n      const droppedBy = ctx.droppedLets?.get(expr.name);\n      if (droppedBy !== undefined) {\n        throw new CodegenError(\n          `\\`${expr.name}\\` is a \\`let\\` binding and can't be read after \\`${droppedBy}\\` \u2014 ` +\n            `the stage replaces the document. Inline the expression into the \\`${droppedBy}\\` body, ` +\n            `or rebind after the stage with another \\`let\\`.`,\n          expr.pos,\n        );\n      }\n      throw new UnknownIdentifierError(expr.name, expr.pos);\n    }\n\n    case \"MemberAccess\": {\n      if (expr.member === \"length\") {\n        return generateLengthAccess(expr.object, expr.optional || chainHasOptional(expr.object), ctx);\n      }\n      const path = asFieldPath(expr, ctx);\n      if (path !== null) return path;\n      // Receiver isn't a foldable field path (e.g. result of $.items[0], a method call,\n      // or a ternary). Use $getField, which works on any expression result.\n      const rawObj = _generate(expr.object, ctx);\n      const obj = expr.optional || chainHasOptional(expr.object) ? wrapIfNull(rawObj, {}) : rawObj;\n      return { $getField: { field: expr.member, input: obj } };\n    }\n\n    case \"MethodCall\":\n      return generateMethodCall(expr.object, expr.method, expr.args, ctx, expr.pos, !!expr.optional);\n\n    case \"CallExpression\":\n      return generateCallExpression(expr.callee, expr.args, ctx, expr.pos);\n\n    case \"Lambda\":\n      throw new CodegenError(\n        \"Lambda expression cannot be used here \u2014 only valid as array method argument or $let second argument\",\n        expr.pos,\n      );\n\n    case \"TypeofExpr\":\n      return { $type: _generate(expr.operand, ctx) };\n\n    case \"NewDate\":\n      return generateNewDate(expr.args, ctx);\n\n    case \"NewSet\":\n      // `new Set(arr)` is a tag for the value \u2014 used as a receiver in set-method calls\n      // (intersection/union/etc.). When evaluated as a standalone value, it just unwraps\n      // to the underlying array (MQL has no Set type).\n      return expr.arg === null ? [] : _generate(expr.arg, ctx);\n\n    case \"ArrayFrom\":\n      return generateArrayFrom(expr.input, expr.mapFn, ctx, expr.pos);\n\n    case \"NumberStatic\":\n      return generateNumberStatic(expr.method, expr.arg, ctx);\n\n    case \"DateNow\":\n      // Date.now() returns ms since epoch \u2014 match JS semantics\n      return { $toLong: \"$$NOW\" };\n\n    case \"DateUTC\":\n      return generateDateUTC(expr.args, ctx);\n\n    case \"TypeCast\":\n      return generateTypeCast(expr.cast, expr.arg, ctx, expr.pos);\n\n    case \"TypeCastRef\":\n      // A bare `Boolean` / `Number` / `String` outside callback position.\n      // Inside `.filter(Boolean)` etc. this node is desugared away in\n      // requireLambda(); reaching this case means the user wrote it as a\n      // value (e.g. `Boolean + 5`), which has no MQL counterpart.\n      throw new CodegenError(\n        `'${expr.cast}' used as a value is only valid as a callback to a higher-order array method (e.g. $.items.filter(${expr.cast})). To coerce a single value, write ${expr.cast}(value).`,\n        expr.pos,\n      );\n\n    case \"MathCall\":\n      return generateMathCall(expr.method, expr.args, ctx, expr.pos);\n\n    case \"MathCallRef\":\n      // A bare `Math.floor` / `Math.round` / \u2026 outside callback position.\n      // In `.map(Math.floor)` etc. this node is desugared away in\n      // requireLambda(); reaching this case means the user wrote it as a\n      // value (e.g. `Math.floor + 5`), which has no MQL counterpart.\n      throw new CodegenError(\n        `'Math.${expr.method}' used as a value is only valid as a callback to a higher-order array method (e.g. $.items.map(Math.${expr.method})). To compute on a single value, write Math.${expr.method}(value).`,\n        expr.pos,\n      );\n\n    case \"MathConst\":\n      return generateMathConst(expr.name);\n\n    case \"ObjectCall\":\n      return generateObjectCall(expr.method, expr.args, ctx, expr.pos);\n  }\n}\n\n// \u2500\u2500 Optional-chaining safety wraps \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// `?.` in jsmql preserves an `optional: true` flag on the AST node the parser\n// produced from it. Codegen consults `chainHasOptional` at every null-unsafe\n// consumer site (array spread, array/string method receivers, string `$concat`\n// operands, template-literal interpolations, `.length`, `Object.keys`/etc.) and\n// wraps the value with `$ifNull(v, neutral)`, where `neutral` is the empty\n// value matching the consumer slot:\n//   - `[]` for array consumers\n//   - `\"\"` for string consumers\n//   - `{}` for object consumers\n//\n// The walker descends only through `MemberAccess` and `IndexAccess` links \u2014 it\n// stops at `MethodCall` because once a method has been called the value is\n// whatever the method returned, not the optional chain that produced its\n// receiver. (The method call site itself already wrapped its receiver if its\n// own chain was optional, so the result is guaranteed safe.) The walker also\n// does not descend into lambda bodies, binary operands, method arguments, or\n// `IndexAccess.index` \u2014 `?.` buried in those positions belongs to a different\n// chain. The current node's own `.optional` flag is consulted separately at\n// each consumer site (see `expr.optional ||` checks in `_generate`).\n\nfunction chainHasOptional(expr: Expr): boolean {\n  let node: Expr = expr;\n  while (node.type === \"MemberAccess\" || node.type === \"IndexAccess\") {\n    if (node.optional) return true;\n    node = node.object;\n  }\n  return false;\n}\n\nfunction wrapIfNull(value: unknown, fallback: unknown): unknown {\n  return { $ifNull: [value, fallback] };\n}\n\n// `.length` / `[\"length\"]` of `object`. Known string \u2192 `$strLenCP`, known array\n// \u2192 `$size`, otherwise dispatch at runtime. When the chain is optional, wrap the\n// receiver with `$ifNull(_, [])` so `$isArray` succeeds, the array branch runs,\n// and `$size([])` returns 0 (matching JS short-circuit: `undefined?.length` is\n// undefined; we surface 0).\nfunction generateLengthAccess(object: Expr, optional: boolean, ctx: GenerateCtx): unknown {\n  const rawObj = _generate(object, ctx);\n  if (isStringProducing(object)) return { $strLenCP: optional ? wrapIfNull(rawObj, \"\") : rawObj };\n  if (isArrayProducing(object)) return { $size: optional ? wrapIfNull(rawObj, []) : rawObj };\n  const obj = optional ? wrapIfNull(rawObj, []) : rawObj;\n  return { $cond: [{ $isArray: obj }, { $size: obj }, { $strLenCP: obj }] };\n}\n\n// Method-name \u2192 \"neutral input for the operator this method lowers to\".\n// Used to pick the `$ifNull` fallback when a `?.` chain feeds the method's\n// receiver. Date / Set / Regex methods are intentionally absent: their\n// underlying operators (`$year`, set ops, regex ops) handle null cleanly and\n// don't poison downstream callers.\n// Derived from METHODS (`optional` field). String-receiver methods pick the\n// `\"\"` neutral, array-receiver methods pick `[]`.\nconst OPTIONAL_STRING_METHODS = methodsWhere((m) => m.optional === \"string\");\n\nconst OPTIONAL_ARRAY_METHODS = methodsWhere((m) => m.optional === \"array\");\n\n// `indexOf` / `includes` / `concat` / `slice` dispatch on receiver type at codegen\n// time (or at runtime via `$cond` when the type is unknown). For these we pick the\n// fallback that matches the chosen branch: `\"\"` when the receiver is provably\n// string-producing, `[]` otherwise \u2014 `[]` is also safe for the runtime-dispatch\n// path because `$isArray([])` is true, sending it down the array branch which\n// returns the same sensible empty-array result the JS short-circuit would.\nconst OPTIONAL_EITHER_METHODS = methodsWhere((m) => m.optional === \"either\");\n\nfunction neutralForMethod(method: string, object: Expr): unknown | undefined {\n  if (OPTIONAL_STRING_METHODS.has(method)) return \"\";\n  if (OPTIONAL_ARRAY_METHODS.has(method)) return [];\n  if (OPTIONAL_EITHER_METHODS.has(method)) {\n    if (isStringProducing(object)) return \"\";\n    return [];\n  }\n  return undefined;\n}\n\n// \u2500\u2500 Field path reconstruction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction asFieldPath(expr: Expr, ctx: GenerateCtx): string | null {\n  if (expr.type === \"FieldRef\") return expr.path === \"\" ? \"$$ROOT\" : `$${expr.path}`;\n  if (expr.type === \"ParamRef\") {\n    if (ctx.reduceRemap?.has(expr.name)) {\n      return `$$${ctx.reduceRemap.get(expr.name)!}`;\n    }\n    if (ctx.lambdaParams.has(expr.name)) {\n      return `$$${expr.name}`;\n    }\n    const letPath = ctx.pipelineLets?.get(expr.name);\n    if (letPath !== undefined) {\n      return `$${letPath}`;\n    }\n    return null;\n  }\n  if (expr.type === \"MemberAccess\") {\n    const base = asFieldPath(expr.object, ctx);\n    if (base !== null) return `${base}.${expr.member}`;\n  }\n  return null;\n}\n\n// \u2500\u2500 Binary expressions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Canonical JS-binary-operator \u2192 MQL-operator-name mapping \u2014 the single source\n * of truth shared between codegen (which emits `{ $op: \u2026 }`) and\n * `match-translation` (which uses the operator name as a query-document key, see\n * its `orderedOpToMql`). Only operators with a *direct* single-operator lowering\n * appear here; the ones with bespoke handling (`+` numeric-vs-string, `==`/`!=`\n * null-only, `&&`/`||` JS-truthy, `in` membership) are not in the table.\n *\n * Two emission groups share it: DIRECT ops lower to `{ $op: [left, right] }`;\n * CHAIN ops (associative) flatten to a flat N-ary array via `flattenChain`.\n */\nconst BINARY_OP_TO_MQL = {\n  \"-\": \"$subtract\",\n  \"/\": \"$divide\",\n  \"%\": \"$mod\",\n  \"**\": \"$pow\",\n  \"===\": \"$eq\",\n  \"!==\": \"$ne\",\n  \">\": \"$gt\",\n  \">=\": \"$gte\",\n  \"<\": \"$lt\",\n  \"<=\": \"$lte\",\n  \"*\": \"$multiply\",\n  \"??\": \"$ifNull\",\n  \"&\": \"$bitAnd\",\n  \"|\": \"$bitOr\",\n  \"^\": \"$bitXor\",\n} as const satisfies Partial<Record<BinaryOp, string>>;\n\ntype DirectBinaryOp = \"-\" | \"/\" | \"%\" | \"**\" | \"===\" | \"!==\" | \">\" | \">=\" | \"<\" | \"<=\";\ntype ChainBinaryOp = \"*\" | \"??\" | \"&\" | \"|\" | \"^\";\n\n/** The MQL operator name for a direct/chain binary op \u2014 the one accessor other\n *  modules use (match-translation's query-document path), so `BINARY_OP_TO_MQL`\n *  stays the single source of truth. */\nexport function mqlForBinaryOp(op: DirectBinaryOp | ChainBinaryOp): string {\n  return BINARY_OP_TO_MQL[op];\n}\n\nfunction generateBinaryExpr(op: BinaryOp, left: Expr, right: Expr, ctx: GenerateCtx, pos: number): unknown {\n  switch (op) {\n    case \"+\":\n      return generateAdd(left, right, ctx);\n    case \"==\":\n    case \"!=\":\n      return generateLooseEquality(op, left, right, ctx, pos);\n    case \"&&\":\n      return generateLogical(\"&&\", left, right, ctx);\n    case \"||\":\n      return generateLogical(\"||\", left, right, ctx);\n    case \"in\":\n      return generateInExpr(left, right, ctx, pos);\n    // Direct binary operators \u2192 `{ $op: [left, right] }`.\n    case \"-\":\n    case \"/\":\n    case \"%\":\n    case \"**\":\n    case \"===\":\n    case \"!==\":\n    case \">\":\n    case \">=\":\n    case \"<\":\n    case \"<=\":\n      return { [BINARY_OP_TO_MQL[op]]: [_generate(left, ctx), _generate(right, ctx)] };\n    // Associative chain operators \u2192 flat N-ary array.\n    case \"*\":\n    case \"??\":\n    case \"&\":\n    case \"|\":\n    case \"^\":\n      return { [BINARY_OP_TO_MQL[op]]: flattenChain(op, left, right, ctx) };\n  }\n}\n\n/**\n * Loose equality (`==`, `!=`) is restricted to comparisons against `null` \u2014\n * the one JS use of `==` that is unambiguous and useful (matches null or\n * missing). Any other use is a footgun (JS type coercion) and is rejected\n * with a message pointing the user at `===`.\n *\n * `$.x == null` compiles to a $type check covering both BSON \"null\" and\n * \"missing\", so missing-field docs match the same way they do in MongoDB's\n * query language (`{ field: null }`). `$.x != null` is the negation.\n */\nfunction generateLooseEquality(op: \"==\" | \"!=\", left: Expr, right: Expr, ctx: GenerateCtx, pos: number): unknown {\n  const leftIsNull = left.type === \"NullLiteral\";\n  const rightIsNull = right.type === \"NullLiteral\";\n  if (!leftIsNull && !rightIsNull) {\n    throw new CodegenError(\n      `'${op}' is only allowed against null in jsmql. Use '${op === \"==\" ? \"===\" : \"!==\"}' for JS-like strict equality (no surprising type coercion). To match \"null or missing\", write '$.x ${op} null'.`,\n      pos,\n    );\n  }\n  const operand = _generate(leftIsNull ? right : left, ctx);\n  const inNullOrMissing = { $in: [{ $type: operand }, [\"null\", \"missing\"]] };\n  return op === \"==\" ? inNullOrMissing : { $not: [inNullOrMissing] };\n}\n\n/**\n * Collect all operands from a left-associative chain of the same operator.\n * e.g. BinaryExpr(*, BinaryExpr(*, a, b), c) \u2192 [gen(a), gen(b), gen(c)]\n */\nfunction flattenChain(op: BinaryOp, left: Expr, right: Expr, ctx: GenerateCtx): unknown[] {\n  const operands: unknown[] = [];\n  collectChain(op, left, operands, ctx);\n  operands.push(_generate(right, ctx));\n  return operands;\n}\n\nfunction collectChain(op: BinaryOp, expr: Expr, out: unknown[], ctx: GenerateCtx): void {\n  if (expr.type === \"BinaryExpr\" && expr.op === op) {\n    collectChain(op, expr.left, out, ctx);\n    out.push(_generate(expr.right, ctx));\n  } else {\n    out.push(_generate(expr, ctx));\n  }\n}\n\n// \u2500\u2500 Logical && / || (operand-preserving, JS semantics) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// JS `a && b` returns `a` if a is falsy, else `b`. JS `a || b` returns `a`\n// if a is truthy, else `b`. The result is the operand, not a boolean \u2014 so\n// `$.x || \"default\"` evaluates to \"default\" only when $.x is JS-falsy, and\n// `[$.b && $.b + \",\"]` includes the concatenation only when $.b is truthy.\n//\n// We compile to `$cond` and bind the LHS once via `$let` when re-evaluating\n// it would be wasteful or unsafe. Pure refs (FieldRef / lambda param /\n// member access on either) compile inline without `$let`.\n//\n// Chains like `a && b && c` are folded right so short-circuit semantics\n// are preserved: `a && (b && c)` \u2192 if a falsy return a, else evaluate b&&c.\n\nfunction generateLogical(op: \"&&\" | \"||\", left: Expr, right: Expr, ctx: GenerateCtx): unknown {\n  const chain: Expr[] = [];\n  collectExprChain(op, left, chain);\n  chain.push(right);\n  return foldLogical(op, chain, ctx);\n}\n\nfunction foldLogical(op: \"&&\" | \"||\", chain: Expr[], ctx: GenerateCtx): unknown {\n  if (chain.length === 1) return _generate(chain[0], ctx);\n  // All-bool chains (or all-bool tails) keep the cheap `$and`/`$or` form.\n  // The result is bool either way \u2014 JS's operand-preserving rule is moot\n  // when every operand is already a boolean. Covers the common filter-\n  // condition case (`x > 0 && y < 10`) and bool-only tails of mixed chains.\n  if (chain.every((e) => isProvablyBool(e))) {\n    const operands = chain.map((e) => _generate(e, ctx));\n    return op === \"&&\" ? { $and: operands } : { $or: operands };\n  }\n  const lhs = chain[0];\n  const lhsGen = _generate(lhs, ctx);\n  const rhsGen = foldLogical(op, chain.slice(1), ctx);\n  // Pure refs and provably-bool LHS values are cheap to reference twice, so\n  // we inline rather than introducing `$let`. (For provably-bool, the value\n  // and its truthiness are the same \u2014 re-eval cost is at most a comparison.)\n  if (isPureRef(lhs, ctx) || isProvablyBool(lhs)) {\n    return condForLogical(op, lhsGen, rhsGen, lhs);\n  }\n  // Bind lhs once so we can both test and return it without re-evaluating.\n  const v = gensymInScope(ctx, \"_v\");\n  const ref = `$$${v}`;\n  return {\n    $let: {\n      vars: { [v]: lhsGen },\n      // The bound value is a runtime value \u2014 we don't have an AST for it,\n      // so we can't ask isProvablyBool. Always wrap in jsBool for the cond.\n      in: condForLogical(op, ref, rhsGen, null),\n    },\n  };\n}\n\nfunction condForLogical(op: \"&&\" | \"||\", lhs: unknown, rhs: unknown, lhsExpr: Expr | null): unknown {\n  const cond = lhsExpr ? jsBoolIfNeeded(lhsExpr, lhs) : jsBool(lhs);\n  return op === \"&&\" ? { $cond: [cond, rhs, lhs] } : { $cond: [cond, lhs, rhs] };\n}\n\n// \u2500\u2500 `in` operator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * `in` straddles two JS semantics depending on the RHS:\n *   - array on the right: value membership (different from JS, which checks\n *     numeric-index existence on arrays \u2014 but value-membership is overwhelmingly\n *     what users want for MongoDB queries, so we deliberately diverge here).\n *   - object on the right: property existence \u2014 JS-faithful.\n *\n * For an object-literal RHS we extract the keys at compile time and reduce to\n * `{ $in: [LHS, [...keys]] }`. Computed keys are evaluated at runtime; spread\n * entries unwrap to `$objectToArray` over the spread expression so the keys\n * become available without us having to know them at compile time.\n *\n * Scalar literals on the right have no useful interpretation in either\n * direction and stay rejected.\n */\nfunction generateInExpr(left: Expr, right: Expr, ctx: GenerateCtx, pos: number): unknown {\n  if (\n    right.type === \"StringLiteral\" ||\n    right.type === \"NumberLiteral\" ||\n    right.type === \"BooleanLiteral\" ||\n    right.type === \"NullLiteral\"\n  ) {\n    throw new CodegenError(\n      \"Right-hand side of 'in' must be an array literal, object literal, or field reference, not a scalar value\",\n      pos,\n    );\n  }\n  if (right.type === \"ObjectLiteral\") {\n    return { $in: [_generate(left, ctx), keyArrayForObjectLiteral(right.entries, ctx)] };\n  }\n  return { $in: [_generate(left, ctx), _generate(right, ctx)] };\n}\n\n/**\n * Build the MQL expression representing the *keys* of an object-literal RHS,\n * for the `key in obj` case. Static-only entries collapse to a literal string\n * array. Computed-key entries emit the key expression directly (it should\n * resolve to a string at runtime). Spread entries lower to\n * `$objectToArray(expr).k` so we can splice the runtime keys in.\n *\n * If every chunk is static the result is a plain JS array; if any spread is\n * present we wrap the chunks in `$concatArrays`.\n */\nfunction keyArrayForObjectLiteral(entries: ObjectEntry[], ctx: GenerateCtx): unknown {\n  // Fast path: all static keys \u2192 a plain literal array of strings.\n  if (entries.every((e) => e.type === \"KeyValueEntry\" && e.key.kind === \"static\")) {\n    return entries.map((e) => ((e as KeyValueEntry).key as { kind: \"static\"; name: string }).name);\n  }\n\n  // Mixed path: build `$concatArrays` of per-chunk operands. Consecutive\n  // non-spread entries group into one literal array (mirrors the array-literal\n  // spread codegen for compact output).\n  const operands: unknown[] = [];\n  let currentChunk: unknown[] | null = null;\n  const flush = () => {\n    if (currentChunk !== null) {\n      operands.push(currentChunk);\n      currentChunk = null;\n    }\n  };\n  for (const entry of entries) {\n    if (entry.type === \"SpreadElement\") {\n      flush();\n      operands.push({ $map: { input: { $objectToArray: _generate(entry.argument, ctx) }, as: \"kv\", in: \"$$kv.k\" } });\n      continue;\n    }\n    if (currentChunk === null) currentChunk = [];\n    currentChunk.push(entry.key.kind === \"static\" ? entry.key.name : _generate(entry.key.expr, ctx));\n  }\n  flush();\n\n  if (operands.length === 1) return operands[0];\n  return { $concatArrays: operands };\n}\n\n// \u2500\u2500 String-context + \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateAdd(left: Expr, right: Expr, ctx: GenerateCtx): unknown {\n  // Collect full operand chain first, then decide $add vs $concat\n  const exprs: Expr[] = [];\n  collectExprChain(\"+\", left, exprs);\n  exprs.push(right);\n\n  const isString = exprs.some((e) => isStringProducing(e));\n  if (isString) {\n    // `$concat` returns null on any null operand, poisoning the whole string.\n    // Wrap optional-chain operands with $ifNull(v, \"\") so `?.` operands match\n    // JS-like fallback semantics for string concatenation.\n    return {\n      $concat: exprs.map((e) => {\n        const gen = _generate(e, ctx);\n        return chainHasOptional(e) ? wrapIfNull(gen, \"\") : gen;\n      }),\n    };\n  }\n  // Numeric `$add` already returns null on null operand, matching JS's\n  // `1 + undefined === NaN` closely enough \u2014 leave optional operands alone\n  // so the result is honestly null rather than silently coerced to 0.\n  return { $add: exprs.map((e) => _generate(e, ctx)) };\n}\n\nfunction collectExprChain(op: BinaryOp, expr: Expr, out: Expr[]): void {\n  if (expr.type === \"BinaryExpr\" && expr.op === op) {\n    collectExprChain(op, expr.left, out);\n    out.push(expr.right);\n  } else {\n    out.push(expr);\n  }\n}\n\n// \u2500\u2500 Unary expressions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateUnaryExpr(op: \"!\" | \"-\" | \"~\", operand: Expr, ctx: GenerateCtx, _pos: number): unknown {\n  if (op === \"!\") {\n    // !!x \u2192 jsBool(x): the canonical \"coerce to JS boolean\" idiom, identical\n    // to what `Boolean(x)` emits. Saves a $not-of-$not.\n    if (operand.type === \"UnaryExpr\" && operand.op === \"!\") {\n      return jsBool(_generate(operand.operand, ctx));\n    }\n    return { $not: jsBoolIfNeeded(operand, _generate(operand, ctx)) };\n  }\n  if (op === \"~\") {\n    return { $bitNot: _generate(operand, ctx) };\n  }\n  // Unary minus: optimise -<number> to a plain negative number literal\n  if (operand.type === \"NumberLiteral\") {\n    return -operand.value;\n  }\n  return { $multiply: [_generate(operand, ctx), -1] };\n}\n\n// \u2500\u2500 Array / object literals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Generate an array literal. Mirrors `generateObjectLiteral`'s spread handling:\n *\n *   - No spread \u2192 plain MQL array of generated elements.\n *   - Any spread (`[1, ...a, 2]`) \u2192 `$concatArrays` over a list of operands, where\n *     consecutive non-spread elements are grouped into one literal-array operand\n *     and each spread argument is its own operand (presumed to evaluate to an\n *     array at runtime).\n *\n * The single-operand case (`[...a]` on its own) returns the spread argument\n * directly \u2014 `{ $concatArrays: [a] }` is semantically equivalent and noisier.\n */\nfunction generateArrayLiteral(elements: ArrayElement[], ctx: GenerateCtx, pos: number): unknown {\n  // Update ops (`$.a = 1`, `delete $.x`) are valid as ArrayElements only when\n  // the array is a pipeline (handled in pipeline.ts before reaching here).\n  // Reaching here with a update op means the user wrote a update op inside a\n  // value array \u2014 reject with a precise error pointing at the supported forms.\n  for (const el of elements) {\n    if (el.type === \"AssignExpr\" || el.type === \"DeleteStmt\") {\n      throw new CodegenError(\n        `${el.type === \"AssignExpr\" ? \"Assignment\" : \"delete\"} is a statement, not a value, and is only valid at the top level or as a pipeline-array element. ` +\n          `If this array is meant to be a pipeline, ensure its first element is a stage like \\`$match(...)\\`.`,\n        el.pos,\n      );\n    }\n    if (el.type === \"LetDecl\") {\n      throw new CodegenError(\n        \"`let` is a pipeline statement, not a value, and is only valid as a pipeline-array element. \" +\n          \"If this array is meant to be a pipeline, ensure its first element is a stage like `$match(...)`.\",\n        el.pos,\n      );\n    }\n  }\n  void pos;\n\n  const hasSpread = elements.some((el) => el.type === \"SpreadElement\");\n\n  if (!hasSpread) {\n    return elements.map((el) => _generate(el as Expr, ctx));\n  }\n\n  const operands: unknown[] = [];\n  let buffer: Expr[] = [];\n\n  const flushBuffer = () => {\n    if (buffer.length === 0) return;\n    operands.push(buffer.map((el) => _generate(el, ctx)));\n    buffer = [];\n  };\n\n  for (const el of elements) {\n    if (el.type === \"SpreadElement\") {\n      flushBuffer();\n      // `[..., ...x?.y, ...]` \u2014 if the spread argument's chain is optional,\n      // wrap with `$ifNull(v, [])` so a missing field produces an empty array\n      // rather than `null` (which poisons `$concatArrays` and crashes any\n      // downstream operator expecting an array).\n      const argVal = _generate(el.argument, ctx);\n      operands.push(chainHasOptional(el.argument) ? wrapIfNull(argVal, []) : argVal);\n    } else if (el.type === \"AssignExpr\" || el.type === \"DeleteStmt\" || el.type === \"LetDecl\") {\n      // Already rejected above; unreachable.\n      continue;\n    } else {\n      buffer.push(el);\n    }\n  }\n  flushBuffer();\n\n  if (operands.length === 1) return operands[0];\n  return { $concatArrays: operands };\n}\n\n/**\n * Generate an object literal. The shape it compiles to depends on which features the\n * source used:\n *\n *   - All static keys, no spread        \u2192 plain MQL object.\n *   - Any computed key, no spread       \u2192 `$arrayToObject` over `[[k, v], ...]`.\n *   - Any spread (`{...a, x: 1, ...b}`) \u2192 `$mergeObjects` over a list of operands,\n *                                         where consecutive non-spread entries are\n *                                         grouped into one operand each (using the\n *                                         same static / `$arrayToObject` rules) and\n *                                         each spread argument is its own operand.\n *\n * The single-operand case (`{...a}` on its own) returns the spread argument directly\n * to avoid emitting a redundant `$mergeObjects: [a]` wrapper \u2014 they're semantically\n * equivalent in MQL.\n */\nfunction generateObjectLiteral(entries: ObjectEntry[], ctx: GenerateCtx, _pos: number): unknown {\n  const hasSpread = entries.some((e) => e.type === \"SpreadElement\");\n\n  if (!hasSpread) {\n    const hasComputed = entries.some((e) => e.type === \"KeyValueEntry\" && e.key.kind === \"computed\");\n    if (!hasComputed) {\n      return generateStaticObjectEntries(entries, ctx);\n    }\n    return generateComputedKeyObject(entries as KeyValueEntry[], ctx);\n  }\n\n  // Spread present: walk entries left-to-right, grouping consecutive non-spread\n  // entries into one $mergeObjects operand each, and emitting each spread argument\n  // as its own operand. JS spread semantics (\"later wins\") match $mergeObjects's\n  // own (\"rightmost value wins on key collision\"), so left-to-right order is\n  // preserved verbatim.\n  const operands: unknown[] = [];\n  let staticBuffer: KeyValueEntry[] = [];\n\n  const flushBuffer = () => {\n    if (staticBuffer.length === 0) return;\n    const hasComputed = staticBuffer.some((e) => e.key.kind === \"computed\");\n    operands.push(\n      hasComputed ? generateComputedKeyObject(staticBuffer, ctx) : generateStaticObjectEntries(staticBuffer, ctx),\n    );\n    staticBuffer = [];\n  };\n\n  for (const entry of entries) {\n    if (entry.type === \"SpreadElement\") {\n      flushBuffer();\n      operands.push(_generate(entry.argument, ctx));\n    } else {\n      staticBuffer.push(entry);\n    }\n  }\n  flushBuffer();\n\n  if (operands.length === 1) return operands[0];\n  return { $mergeObjects: operands };\n}\n\nfunction generateComputedKeyObject(entries: KeyValueEntry[], ctx: GenerateCtx): unknown {\n  const pairs = entries.map((entry) => {\n    const key = entry.key.kind === \"static\" ? entry.key.name : _generate(entry.key.expr, ctx);\n    return [key, _generate(entry.value, ctx)];\n  });\n  return { $arrayToObject: pairs };\n}\n\n/**\n * Used for object-style operator args, where the keys must literally appear in MQL output\n * (e.g. `{ input, find, replacement }` for `$replaceOne`). Computed keys are rejected here \u2014\n * MongoDB operator key names are part of the operator's wire format and can't be runtime values.\n */\nfunction generateStaticObjectEntries(entries: ObjectEntry[], ctx: GenerateCtx): Record<string, unknown> {\n  const result: Record<string, unknown> = {};\n  for (const entry of entries) {\n    if (entry.type === \"SpreadElement\") {\n      throw new CodegenError(\"Spread elements in objects are not supported in MQL output\", entry.pos);\n    }\n    if (entry.key.kind === \"computed\") {\n      throw new CodegenError(\n        \"Computed object keys are not allowed here \u2014 operator argument keys must be literal names\",\n        entry.pos,\n      );\n    }\n    result[entry.key.name] = _generate(entry.value, ctx);\n  }\n  return result;\n}\n\n// \u2500\u2500 Operator calls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Validate that an operator call appears in a context that allows it. Throws\n * a precise `CodegenError` for window-only / accumulator-only operators used\n * outside `$group` / `$setWindowFields.output`. Permissive by default \u2014 any\n * operator whose category is `window` or whose `accumulatorOnly` flag is set\n * gets gated; everything else passes through.\n *\n * Accumulator-only operators have no expression-form in MongoDB \u2014 they only\n * mean something inside `$group` field-value slots or `$setWindowFields.output`\n * bodies, so using them elsewhere produces invalid MQL the server would reject\n * at runtime. The `accumulatorOnly` flag lives on the operator registry entry\n * ([operators.ts](operators.ts)) \u2014 the single source of truth \u2014 so it stays\n * distinct from ops with *both* expression and accumulator forms ($sum, $avg,\n * $max, $min, $stdDev*), which leave the flag unset and stay unrestricted.\n */\nfunction checkOperatorContext(name: string, ctx: GenerateCtx, pos: number): void {\n  const def = lookupOperator(name);\n  // Window-only: category === \"window\" \u2192 require `window-output` context.\n  if (def?.category === \"window\") {\n    if (ctx.accumulatorContext !== \"window-output\") {\n      throw new CodegenError(\n        `${name} is a window operator \u2014 only valid inside '$setWindowFields' output slots. ` +\n          `Use $setWindowFields({ partitionBy: ..., sortBy: ..., output: { <key>: ${name}(...) } }) to compute it per-document over a window.`,\n        pos,\n      );\n    }\n    return;\n  }\n  // Accumulator-only: allowed inside `$group` field-value slots and inside\n  // `$setWindowFields.output` slots.\n  if (def?.accumulatorOnly) {\n    if (ctx.accumulatorContext === undefined) {\n      throw new CodegenError(\n        `${name} is an accumulator operator \u2014 only valid inside '$group' field-value slots or '$setWindowFields' output slots. ` +\n          `Use $group({ _id: ..., <key>: ${name}(...) }) to compute it per-group, or $setWindowFields(...) for the windowed form.`,\n        pos,\n      );\n    }\n  }\n}\n\nfunction generateOperatorCall(\n  name: string,\n  style: \"positional\" | \"object\",\n  args: CallArg[],\n  ctx: GenerateCtx,\n  pos: number,\n): Record<string, unknown> {\n  checkOperatorContext(name, ctx, pos);\n  // Special case: $literal(value) \u2014 the argument is wrapped verbatim and\n  // MongoDB does not re-evaluate it at query time. Recurse with the\n  // `insideLiteral` flag so nested `\"$...\"` strings don't get a second\n  // `$literal` wrap (that would emit a literal-of-a-literal object). Sits\n  // ahead of the `style === \"object\"` branch because the parser tags\n  // `$literal({...})` as object-style, but we still want the suppress flag.\n  if (name === \"$literal\" && args.length === 1 && args[0].type !== \"SpreadElement\") {\n    const inner = _generate(args[0] as Expr, { ...ctx, insideLiteral: true });\n    return { $literal: inner };\n  }\n\n  if (style === \"object\") {\n    const objArg = args[0];\n    if (!objArg || objArg.type !== \"ObjectLiteral\") {\n      throw new CodegenError(`Object-style call to ${name} must have exactly one object argument`, pos);\n    }\n    const def = lookupOperator(name);\n    // For operators that genuinely expect a named-key object (e.g. $trim, $dateAdd),\n    // the keys must be literal names \u2014 they are part of the MQL wire format.\n    // For any other operator (or unknown), the object is just a value, so computed\n    // keys and any other normal object behaviour applies.\n    if (def?.shape.kind === \"object\") {\n      return { [name]: generateStaticObjectEntries(objArg.entries, ctx) };\n    }\n    return { [name]: generateObjectLiteral(objArg.entries, ctx, objArg.pos) };\n  }\n\n  // Special case: $let(varsObj, lambda) \u2014 lambda defines the \"in\" body\n  if (name === \"$let\" && args.length === 2 && args[1]?.type === \"Lambda\") {\n    const varsExpr = args[0];\n    if (!varsExpr || varsExpr.type !== \"ObjectLiteral\") {\n      throw new CodegenError(\"$let first argument must be an object literal\", varsExpr?.pos ?? pos);\n    }\n    const lambdaExpr = args[1];\n    if (lambdaExpr.type !== \"Lambda\") throw new CodegenError(\"$let second argument must be a lambda\", lambdaExpr.pos);\n    if (lambdaExpr.body === undefined) {\n      throw new CodegenError(\n        \"$let second argument cannot be a block-body arrow \u2014 only '$$$.<coll>.find/filter(...)' accepts block bodies.\",\n        lambdaExpr.pos,\n      );\n    }\n    const vars = generateStaticObjectEntries(varsExpr.entries, ctx);\n    const bodyCtx = extendCtx(ctx, lambdaExpr.params);\n    return { $let: { vars, in: _generate(lambdaExpr.body, bodyCtx) } };\n  }\n\n  const def = lookupOperator(name);\n\n  if (!def) {\n    return generateUnknownOperator(name, args, ctx);\n  }\n\n  const { shape } = def;\n\n  switch (shape.kind) {\n    case \"none\": {\n      assertNoSpread(args, name, pos);\n      return { [name]: {} };\n    }\n\n    case \"single\": {\n      assertNoSpread(args, name, pos);\n      if (args.length !== 1) {\n        throw new CodegenError(`Operator ${name} expects exactly 1 argument, got ${args.length}`, pos);\n      }\n      return { [name]: _generate(args[0] as Expr, ctx) };\n    }\n\n    case \"array\": {\n      if (args.length === 0) {\n        throw new CodegenError(`Operator ${name} expects at least 1 argument`, pos);\n      }\n      return { [name]: generateVariadicArgs(args, ctx) };\n    }\n\n    case \"flex\": {\n      // Flex: 1 arg \u2192 `{ $op: expr }`, 2+ \u2192 `{ $op: [a, b, ...] }`.\n      // A single spread (`...arr`) collapses to the single form, passing the array through.\n      if (args.length === 0) {\n        throw new CodegenError(`Operator ${name} expects at least 1 argument`, pos);\n      }\n      if (args.length === 1) {\n        const only = args[0];\n        if (only.type === \"SpreadElement\") {\n          return { [name]: _generate(only.argument, ctx) };\n        }\n        return { [name]: _generate(only, ctx) };\n      }\n      return { [name]: generateVariadicArgs(args, ctx) };\n    }\n\n    case \"object\": {\n      assertNoSpread(args, name, pos);\n      if (args.length === 0) {\n        throw new CodegenError(`Operator ${name} expects at least 1 argument`, pos);\n      }\n      const keys = shape.keys;\n      const obj: Record<string, unknown> = {};\n      for (let i = 0; i < args.length; i++) {\n        const key = keys[i];\n        if (!key) {\n          throw new CodegenError(\n            `Operator ${name} received more positional arguments than expected (max ${keys.length})`,\n            (args[i] as Expr | SpreadElement).pos,\n          );\n        }\n        obj[key] = _generate(args[i] as Expr, ctx);\n      }\n      return { [name]: obj };\n    }\n  }\n}\n\nfunction generateUnknownOperator(name: string, args: CallArg[], ctx: GenerateCtx): Record<string, unknown> {\n  if (args.length === 0) {\n    return { [name]: {} };\n  }\n  if (args.length === 1) {\n    const only = args[0];\n    if (only.type === \"SpreadElement\") {\n      // Single ...arr passes the spread argument through directly as the operator value.\n      return { [name]: _generate(only.argument, ctx) };\n    }\n    if (only.type === \"ObjectLiteral\") {\n      return { [name]: generateStaticObjectEntries(only.entries, ctx) };\n    }\n    return { [name]: _generate(only, ctx) };\n  }\n  return { [name]: generateVariadicArgs(args, ctx) };\n}\n\n/**\n * Generate a variadic argument list, handling spread via concatArrays.\n *\n *   - all-non-spread args \u2192 a flat array\n *   - single spread arg \u2192 the spread's value (which is presumed to be an array)\n *   - mixed \u2192 `{ $concatArrays: [...wrapped] }`, where non-spread args become single-element arrays\n *     and spread args are passed through as their array value.\n */\nfunction generateVariadicArgs(args: CallArg[], ctx: GenerateCtx): unknown {\n  const hasSpread = args.some((a) => a.type === \"SpreadElement\");\n  if (!hasSpread) {\n    return args.map((a) => _generate(a as Expr, ctx));\n  }\n  if (args.length === 1) {\n    const only = args[0] as SpreadElement;\n    return _generate(only.argument, ctx);\n  }\n  const parts = args.map((a) => (a.type === \"SpreadElement\" ? _generate(a.argument, ctx) : [_generate(a, ctx)]));\n  return { $concatArrays: parts };\n}\n\nfunction assertNoSpread(args: CallArg[], name: string, callPos: number): void {\n  for (const a of args) {\n    if (a.type === \"SpreadElement\") {\n      throw new CodegenError(\n        `Spread (...) is not supported as an argument to ${name} \u2014 only variadic operators accept it`,\n        a.pos ?? callPos,\n      );\n    }\n  }\n}\n\n// \u2500\u2500 Template literals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Compile a template literal to `$concat`. Empty quasis and adjacent expressions are\n * still emitted as literal strings to keep the structure faithful \u2014 MongoDB will see\n * exactly the chunks the user wrote.\n *\n * `\\`hello, ${name}!\\`` \u2192 `{ $concat: [\"hello, \", expr_for_name, \"!\"] }`\n *\n * Non-string interpolations are wrapped with `$toString` to match JS semantics \u2014\n * `\\`count: ${$.n}\\`` works whether `$.n` is a number or a string. Expressions that\n * are statically known to produce strings skip the wrap to keep output compact.\n *\n * Special case: a template with no expressions and a single quasi just returns that\n * string (so `\\`hi\\`` \u2261 `\"hi\"`).\n */\nfunction generateTemplateLiteral(quasis: string[], expressions: Expr[], ctx: GenerateCtx): unknown {\n  if (expressions.length === 0) {\n    return quasis[0] ?? \"\";\n  }\n  const parts: unknown[] = [];\n  for (let i = 0; i < expressions.length; i++) {\n    if (quasis[i] !== \"\") parts.push(quasis[i]);\n    const expr = expressions[i];\n    const gen = _generate(expr, ctx);\n    // Template literals lower to `$concat`, which is null-poisoning. When the\n    // interpolation's chain has `?.`, wrap with `$ifNull(v, \"\")` before\n    // `$toString` so a missing field produces `\"\"` rather than `null` (which\n    // would collapse the whole template). JS would produce `\"undefined\"` here;\n    // `\"\"` is the saner empty for templates.\n    const wrappedGen = chainHasOptional(expr) ? wrapIfNull(gen, \"\") : gen;\n    parts.push(isStringProducing(expr) ? wrappedGen : { $toString: wrappedGen });\n  }\n  const tail = quasis[expressions.length];\n  if (tail !== \"\") parts.push(tail);\n  return { $concat: parts };\n}\n\n// \u2500\u2500 Method calls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateMethodCall(\n  object: Expr,\n  method: string,\n  args: CallArg[],\n  ctx: GenerateCtx,\n  callPos: number,\n  optional: boolean = false,\n): unknown {\n  // \u2500\u2500 Set receiver: new Set(arr).intersection / union / difference / ... \u2500\u2500\u2500\u2500\u2500\n  if (object.type === \"NewSet\") {\n    return generateSetMethodCall(object, method, args, ctx);\n  }\n  // \u2500\u2500 Regex receiver: /pat/flags.test(str) / .exec(str) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  if (object.type === \"RegexLiteral\") {\n    return generateRegexMethodCall(object, method, args, ctx);\n  }\n\n  // When `?.` appears on this method call itself or anywhere in the receiver's\n  // postfix chain, wrap the receiver with `$ifNull(v, neutral)` so the called\n  // operator receives an empty value of the right type instead of null\n  // (which would either error or poison downstream callers).\n  const rawObj = _generate(object, ctx);\n  const wrapReceiver = optional || chainHasOptional(object);\n  const neutral = wrapReceiver ? neutralForMethod(method, object) : undefined;\n  const genObj = neutral !== undefined ? wrapIfNull(rawObj, neutral) : rawObj;\n\n  switch (method) {\n    // \u2500\u2500 String methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    case \"trim\":\n      return { $trim: { input: genObj } };\n    case \"trimStart\":\n    case \"trimLeft\":\n      return { $ltrim: { input: genObj } };\n    case \"trimEnd\":\n    case \"trimRight\":\n      return { $rtrim: { input: genObj } };\n    case \"toLowerCase\":\n      return { $toLower: genObj };\n    case \"toUpperCase\":\n      return { $toUpper: genObj };\n    case \"substr\": {\n      const exprArgs = exprArgsOnly(args, \"substr\");\n      checkArity(\"substr\", { sig: \"start[, count]\", allowed: [1, 2] }, exprArgs.length, callPos);\n      if (exprArgs.length === 1) {\n        return { $substrCP: [genObj, _generate(exprArgs[0], ctx), { $strLenCP: genObj }] };\n      }\n      return { $substrCP: [genObj, _generate(exprArgs[0], ctx), _generate(exprArgs[1], ctx)] };\n    }\n    case \"substring\": {\n      const exprArgs = exprArgsOnly(args, \"substring\");\n      checkArity(\"substring\", { sig: \"start[, end]\", allowed: [0, 1, 2] }, exprArgs.length, callPos);\n      if (exprArgs.length === 0) return genObj;\n      // JS .substring(s, e) takes end-exclusive; MQL $substrCP takes a length.\n      // JS clamps negative indices to 0 (and would also swap if start > end \u2014\n      // we model the clamping but not the swap; see docs/specs/string-methods.md).\n      const start = clampNonNegativeIndex(exprArgs[0], ctx);\n      if (exprArgs.length === 1) {\n        return { $substrCP: [genObj, start, foldedSubtract({ $strLenCP: genObj }, start)] };\n      }\n      const end = clampNonNegativeIndex(exprArgs[1], ctx);\n      return { $substrCP: [genObj, start, clampNonNegativeLength(foldedSubtract(end, start))] };\n    }\n    case \"charAt\": {\n      const exprArgs = exprArgsOnly(args, \"charAt\");\n      checkArity(\"charAt\", { sig: \"index\", exact: 1 }, exprArgs.length, callPos);\n      return { $substrCP: [genObj, _generate(exprArgs[0], ctx), 1] };\n    }\n    case \"split\": {\n      const exprArgs = exprArgsOnly(args, \"split\");\n      checkArity(\"split\", { sig: \"separator\", exact: 1 }, exprArgs.length, callPos);\n      return { $split: [genObj, _generate(exprArgs[0], ctx)] };\n    }\n    case \"startsWith\": {\n      const exprArgs = exprArgsOnly(args, \"startsWith\");\n      checkArity(\"startsWith\", { sig: \"searchString\", exact: 1 }, exprArgs.length, callPos);\n      return { $eq: [{ $indexOfCP: [genObj, _generate(exprArgs[0], ctx)] }, 0] };\n    }\n    case \"endsWith\": {\n      const exprArgs = exprArgsOnly(args, \"endsWith\");\n      checkArity(\"endsWith\", { sig: \"searchString\", exact: 1 }, exprArgs.length, callPos);\n      const needle = _generate(exprArgs[0], ctx);\n      // Compares the last N codepoints of the input with the needle, where N is the needle's length.\n      return {\n        $eq: [\n          { $substrCP: [genObj, { $subtract: [{ $strLenCP: genObj }, { $strLenCP: needle }] }, { $strLenCP: needle }] },\n          needle,\n        ],\n      };\n    }\n    case \"indexOf\": {\n      const exprArgs = exprArgsOnly(args, \"indexOf\");\n      checkArity(\"indexOf\", { sig: \"searchValue\", exact: 1 }, exprArgs.length, callPos);\n      const needle = _generate(exprArgs[0], ctx);\n      // Type-aware dispatch: known array \u2192 $indexOfArray; known string \u2192 $indexOfCP;\n      // unknown \u2192 runtime $cond on $isArray so the right form runs at query time.\n      if (isArrayProducing(object)) {\n        return { $indexOfArray: [genObj, needle] };\n      }\n      if (isStringProducing(object)) {\n        return { $indexOfCP: [genObj, needle] };\n      }\n      return { $cond: [{ $isArray: genObj }, { $indexOfArray: [genObj, needle] }, { $indexOfCP: [genObj, needle] }] };\n    }\n    case \"lastIndexOf\": {\n      const exprArgs = exprArgsOnly(args, \"lastIndexOf\");\n      checkArity(\"lastIndexOf\", { sig: \"searchValue\", exact: 1 }, exprArgs.length, callPos);\n      if (isStringProducing(object)) {\n        throw new CodegenError(\n          `.lastIndexOf() on strings isn't supported \u2014 MongoDB's \\$indexOfCP is forward-only. Use \\$op($indexOfCP, str, needle) for first-match indexing.`,\n          callPos,\n        );\n      }\n      const needle = _generate(exprArgs[0], ctx);\n      // Find the first match in the reversed array, then map back to the original index.\n      // Wrap with $let so genObj is evaluated once.\n      return {\n        $let: {\n          vars: { jsmqlArr: genObj },\n          in: {\n            $let: {\n              vars: { jsmqlRevIdx: { $indexOfArray: [{ $reverseArray: \"$$jsmqlArr\" }, needle] } },\n              in: {\n                $cond: [\n                  { $eq: [\"$$jsmqlRevIdx\", -1] },\n                  -1,\n                  { $subtract: [{ $subtract: [{ $size: \"$$jsmqlArr\" }, 1] }, \"$$jsmqlRevIdx\"] },\n                ],\n              },\n            },\n          },\n        },\n      };\n    }\n    case \"replace\": {\n      const exprArgs = exprArgsOnly(args, \"replace\");\n      checkArity(\"replace\", { sig: \"find, replacement\", exact: 2 }, exprArgs.length, callPos);\n      return {\n        $replaceOne: { input: genObj, find: _generate(exprArgs[0], ctx), replacement: _generate(exprArgs[1], ctx) },\n      };\n    }\n    case \"replaceAll\": {\n      const exprArgs = exprArgsOnly(args, \"replaceAll\");\n      checkArity(\"replaceAll\", { sig: \"find, replacement\", exact: 2 }, exprArgs.length, callPos);\n      return {\n        $replaceAll: { input: genObj, find: _generate(exprArgs[0], ctx), replacement: _generate(exprArgs[1], ctx) },\n      };\n    }\n    case \"includes\": {\n      const exprArgs = exprArgsOnly(args, \"includes\");\n      checkArity(\"includes\", { sig: \"searchValue\", exact: 1 }, exprArgs.length, callPos);\n      const needle = _generate(exprArgs[0], ctx);\n      // Type-aware dispatch: known array \u2192 $in; known string \u2192 $indexOfCP form;\n      // unknown \u2192 runtime $cond so a bare $.field works for either type.\n      if (isArrayProducing(object)) {\n        return { $in: [needle, genObj] };\n      }\n      if (isStringProducing(object)) {\n        return { $gte: [{ $indexOfCP: [genObj, needle] }, 0] };\n      }\n      return {\n        $cond: [{ $isArray: genObj }, { $in: [needle, genObj] }, { $gte: [{ $indexOfCP: [genObj, needle] }, 0] }],\n      };\n    }\n    case \"match\": {\n      const exprArgs = exprArgsOnly(args, \"match\");\n      checkArity(\"match\", { sig: \"regex\", exact: 1 }, exprArgs.length, callPos);\n      const pattern = exprArgs[0];\n      if (pattern.type === \"RegexLiteral\") {\n        const result: Record<string, unknown> = { input: genObj, regex: pattern.pattern };\n        if (pattern.flags) result[\"options\"] = pattern.flags;\n        return { $regexMatch: result };\n      }\n      return { $regexMatch: { input: genObj, regex: _generate(pattern, ctx) } };\n    }\n    case \"matchAll\": {\n      const exprArgs = exprArgsOnly(args, \"matchAll\");\n      checkArity(\"matchAll\", { sig: \"regex\", exact: 1 }, exprArgs.length, callPos);\n      const pattern = exprArgs[0];\n      if (pattern.type === \"RegexLiteral\") {\n        if (!pattern.flags.includes(\"g\")) {\n          throw new CodegenError(\n            `.matchAll() requires a regex with the 'g' flag (matching JS's TypeError on non-global regex)`,\n            callPos,\n          );\n        }\n        const result: Record<string, unknown> = { input: genObj, regex: pattern.pattern };\n        if (pattern.flags) result[\"options\"] = pattern.flags;\n        return { $regexFindAll: result };\n      }\n      return { $regexFindAll: { input: genObj, regex: _generate(pattern, ctx) } };\n    }\n    case \"search\": {\n      const exprArgs = exprArgsOnly(args, \"search\");\n      checkArity(\"search\", { sig: \"regex\", exact: 1 }, exprArgs.length, callPos);\n      const pattern = exprArgs[0];\n      // .search returns the index of the first match, or -1. $regexFind returns\n      // an object with .idx for matches; null on no match. We surface .idx with\n      // an $ifNull fallback to -1 to match JS semantics exactly.\n      const findCall =\n        pattern.type === \"RegexLiteral\"\n          ? {\n              $regexFind: pattern.flags\n                ? { input: genObj, regex: pattern.pattern, options: pattern.flags }\n                : { input: genObj, regex: pattern.pattern },\n            }\n          : { $regexFind: { input: genObj, regex: _generate(pattern, ctx) } };\n      return { $ifNull: [{ $getField: { field: \"idx\", input: findCall } }, -1] };\n    }\n    case \"padStart\":\n    case \"padEnd\": {\n      const exprArgs = exprArgsOnly(args, method);\n      checkArity(method, { sig: \"targetLength[, padString]\", allowed: [1, 2] }, exprArgs.length, callPos);\n      const target = _generate(exprArgs[0], ctx);\n      const pad = exprArgs.length === 2 ? _generate(exprArgs[1], ctx) : \" \";\n      // If str length >= target, return str. Otherwise build pad-str of (target - len)\n      // chars by reducing $range, then concat str on the appropriate side.\n      const padReduce = {\n        $reduce: {\n          input: { $range: [0, { $subtract: [target, { $strLenCP: \"$$s\" }] }] },\n          initialValue: \"\",\n          in: { $concat: [\"$$value\", pad] },\n        },\n      };\n      const concatOrder = method === \"padStart\" ? [padReduce, \"$$s\"] : [\"$$s\", padReduce];\n      return {\n        $let: {\n          vars: { s: genObj },\n          in: { $cond: [{ $gte: [{ $strLenCP: \"$$s\" }, target] }, \"$$s\", { $concat: concatOrder }] },\n        },\n      };\n    }\n    case \"repeat\": {\n      const exprArgs = exprArgsOnly(args, \"repeat\");\n      checkArity(\"repeat\", { sig: \"count\", exact: 1 }, exprArgs.length, callPos);\n      const count = _generate(exprArgs[0], ctx);\n      return { $reduce: { input: { $range: [0, count] }, initialValue: \"\", in: { $concat: [\"$$value\", genObj] } } };\n    }\n\n    // \u2500\u2500 Array methods (no lambda) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    case \"at\": {\n      const exprArgs = exprArgsOnly(args, \"at\");\n      checkArity(\"at\", { sig: \"index\", exact: 1 }, exprArgs.length, callPos);\n      return { $arrayElemAt: [genObj, _generate(exprArgs[0], ctx)] };\n    }\n    case \"slice\": {\n      const exprArgs = exprArgsOnly(args, \"slice\");\n      checkArity(\"slice\", { sig: \"start[, end]\", allowed: [0, 1, 2] }, exprArgs.length, callPos);\n      // Receiver-type dispatch: known array \u2192 $slice (native negative-index support);\n      // known string \u2192 $substrCP (with compile-time/runtime normalisation of negatives);\n      // unknown \u2192 runtime $cond on $isArray so a bare $.field works for either type.\n      if (isStringProducing(object)) return sliceString(genObj, exprArgs, ctx);\n      if (isArrayProducing(object)) return sliceArray(genObj, exprArgs, ctx);\n      return { $cond: [{ $isArray: genObj }, sliceArray(genObj, exprArgs, ctx), sliceString(genObj, exprArgs, ctx)] };\n    }\n    case \"toReversed\": {\n      checkArity(method, { sig: \"\", none: true }, args.length, callPos);\n      return { $reverseArray: genObj };\n    }\n    case \"toSorted\": {\n      if (args.length === 0) {\n        return { $sortArray: { input: genObj, sortBy: 1 } };\n      }\n      const exprArgs = exprArgsOnly(args, \"toSorted\");\n      checkArity(\"toSorted\", { sig: \"keyFn\", allowed: [0, 1] }, exprArgs.length, callPos);\n      const sortBy = lambdaToSortBy(exprArgs[0], \"toSorted\");\n      return { $sortArray: { input: genObj, sortBy } };\n    }\n    case \"toSpliced\": {\n      const exprArgs = exprArgsOnly(args, \"toSpliced\");\n      checkArity(\"toSpliced\", { sig: \"start[, deleteCount, ...items]\", atLeast: 1 }, exprArgs.length, callPos);\n      const startArg = exprArgs[0];\n      if (isNegativeLiteral(startArg)) {\n        throw new CodegenError(\n          `.toSpliced() with a negative start index isn't supported \u2014 MongoDB \\$slice's position arg is non-negative.`,\n          startArg.pos,\n        );\n      }\n      const start = _generate(startArg, ctx);\n      // deleteCount omitted \u21D2 remove to end. Match JS exactly.\n      const hasDeleteCount = exprArgs.length >= 2;\n      const deleteCountArg = hasDeleteCount ? exprArgs[1] : null;\n      if (deleteCountArg && isNegativeLiteral(deleteCountArg)) {\n        throw new CodegenError(\n          `.toSpliced() with a negative deleteCount isn't supported \u2014 MongoDB \\$slice's length arg is non-negative.`,\n          deleteCountArg.pos,\n        );\n      }\n      const items = exprArgs.slice(2).map((a) => _generate(a, ctx));\n      // Bind arr/start/end once: $let so size & arithmetic are computed a single time.\n      // tailStart = start + deleteCount, or just start if deleteCount omitted (no removal, pure insert).\n      // tailLen = $size - tailStart, clamped non-negative.\n      const tailStart = hasDeleteCount ? { $add: [\"$$jsmqlStart\", _generate(deleteCountArg!, ctx)] } : \"$$jsmqlStart\";\n      return {\n        $let: {\n          vars: { jsmqlArr: genObj, jsmqlStart: start },\n          in: {\n            $let: {\n              vars: { jsmqlTailStart: tailStart },\n              in: {\n                $concatArrays: [\n                  { $slice: [\"$$jsmqlArr\", 0, \"$$jsmqlStart\"] },\n                  items,\n                  {\n                    $slice: [\n                      \"$$jsmqlArr\",\n                      \"$$jsmqlTailStart\",\n                      { $max: [0, { $subtract: [{ $size: \"$$jsmqlArr\" }, \"$$jsmqlTailStart\"] }] },\n                    ],\n                  },\n                ],\n              },\n            },\n          },\n        },\n      };\n    }\n    case \"with\": {\n      const exprArgs = exprArgsOnly(args, \"with\");\n      checkArity(\"with\", { sig: \"index, value\", exact: 2 }, exprArgs.length, callPos);\n      const idxArg = exprArgs[0];\n      if (isNegativeLiteral(idxArg)) {\n        throw new CodegenError(\n          `.with() with a negative index isn't supported \u2014 MongoDB \\$slice's position arg is non-negative.`,\n          idxArg.pos,\n        );\n      }\n      const idx = _generate(idxArg, ctx);\n      const value = _generate(exprArgs[1], ctx);\n      return {\n        $let: {\n          vars: { jsmqlArr: genObj, jsmqlIdx: idx, jsmqlVal: value },\n          in: {\n            $concatArrays: [\n              { $slice: [\"$$jsmqlArr\", 0, \"$$jsmqlIdx\"] },\n              [\"$$jsmqlVal\"],\n              {\n                $slice: [\n                  \"$$jsmqlArr\",\n                  { $add: [\"$$jsmqlIdx\", 1] },\n                  { $max: [0, { $subtract: [{ $size: \"$$jsmqlArr\" }, { $add: [\"$$jsmqlIdx\", 1] }] }] },\n                ],\n              },\n            ],\n          },\n        },\n      };\n    }\n    case \"findLast\": {\n      const lambda = requireLambda(exprArgsOnly(args, \"findLast\"), \"findLast\", callPos);\n      const iter = arrayIterInput(lambda, genObj, ctx, \"findLast\");\n      const cond = iter.wrap(jsBoolIfNeeded(lambda.body, _generate(lambda.body, iter.bodyCtx)));\n      if (lambda.params.length <= 1) {\n        return { $arrayElemAt: [{ $filter: { input: iter.input, as: iter.asName, cond } }, -1] };\n      }\n      return { $arrayElemAt: [{ $arrayElemAt: [{ $filter: { input: iter.input, as: iter.asName, cond } }, -1] }, 1] };\n    }\n    case \"findIndex\":\n    case \"findLastIndex\": {\n      const lambda = requireLambda(exprArgsOnly(args, method), method, callPos);\n      if (lambda.params.length >= 3) {\n        throw new CodegenError(\n          `.${method}() callbacks take at most 2 parameters (element, index); the third 'array' argument isn't supported. Reference the receiver directly instead.`,\n          lambda.pos,\n        );\n      }\n      const bodyCtx = extendCtx(ctx, lambda.params);\n      // Reduce over [(index, element), ...] pairs. $let rebinds the user-named\n      // params to the pair components so the predicate body's $$<param>\n      // references resolve correctly. For findIndex we want the *first* match \u2014\n      // guard the update with `$$value == -1` so later matches don't overwrite.\n      // For findLastIndex any match overwrites, so the final value is the last.\n      const vars: Record<string, unknown> = { [lambda.params[0]]: { $arrayElemAt: [\"$$this\", 1] } };\n      if (lambda.params[1]) {\n        vars[lambda.params[1]] = { $arrayElemAt: [\"$$this\", 0] };\n      }\n      const predicate = jsBoolIfNeeded(lambda.body, _generate(lambda.body, bodyCtx));\n      const cond = method === \"findIndex\" ? { $and: [{ $eq: [\"$$value\", -1] }, predicate] } : predicate;\n      return {\n        $reduce: {\n          input: { $zip: { inputs: [{ $range: [0, { $size: genObj }] }, genObj] } },\n          initialValue: -1,\n          in: { $let: { vars, in: { $cond: [cond, { $arrayElemAt: [\"$$this\", 0] }, \"$$value\"] } } },\n        },\n      };\n    }\n    case \"concat\": {\n      // Type-aware: known array \u2192 $concatArrays; known string \u2192 $concat;\n      // unknown \u2192 runtime $cond on $isArray so the right form runs at query time.\n      checkArity(\"concat\", { sig: \"...items\", atLeast: 1 }, args.length, callPos);\n      const tail = args.map((a) => (a.type === \"SpreadElement\" ? _generate(a.argument, ctx) : _generate(a, ctx)));\n      if (isArrayProducing(object)) {\n        return { $concatArrays: [genObj, ...tail] };\n      }\n      if (isStringProducing(object)) {\n        return { $concat: [genObj, ...tail] };\n      }\n      return { $cond: [{ $isArray: genObj }, { $concatArrays: [genObj, ...tail] }, { $concat: [genObj, ...tail] }] };\n    }\n    case \"join\": {\n      const exprArgs = exprArgsOnly(args, \"join\");\n      checkArity(\"join\", { sig: \"separator\", allowed: [0, 1] }, exprArgs.length, callPos);\n      const sep = exprArgs.length === 1 ? _generate(exprArgs[0], ctx) : \",\";\n      // Reduce: concatenate elements with the separator, omitting it for the first element.\n      // The accumulator carries the running string; an empty start lets us detect \"first\".\n      return {\n        $reduce: {\n          input: genObj,\n          initialValue: \"\",\n          in: {\n            $cond: [\n              { $eq: [\"$$value\", \"\"] },\n              { $toString: \"$$this\" },\n              { $concat: [\"$$value\", sep, { $toString: \"$$this\" }] },\n            ],\n          },\n        },\n      };\n    }\n    case \"toString\": {\n      checkArity(\"toString\", { sig: \"\", none: true }, args.length, callPos);\n      // JS Array.prototype.toString is `.join(\",\")`. For known string receivers\n      // this is a no-op. For other scalars MongoDB's $toString covers it\n      // (numbers, dates \u2192 ISO string, booleans, ObjectId, etc.).\n      if (isArrayProducing(object)) {\n        return {\n          $reduce: {\n            input: genObj,\n            initialValue: \"\",\n            in: {\n              $cond: [\n                { $eq: [\"$$value\", \"\"] },\n                { $toString: \"$$this\" },\n                { $concat: [\"$$value\", \",\", { $toString: \"$$this\" }] },\n              ],\n            },\n          },\n        };\n      }\n      if (isStringProducing(object)) {\n        return genObj;\n      }\n      return { $toString: genObj };\n    }\n    case \"flat\": {\n      const exprArgs = exprArgsOnly(args, \"flat\");\n      checkArity(\"flat\", { sig: \"depth\", allowed: [0, 1] }, exprArgs.length, callPos);\n      // We only support depth=1 (default). MongoDB has no recursive-depth flatten;\n      // emulating arbitrary depths would require unbounded $reduce nesting.\n      if (exprArgs.length === 1) {\n        const arg = exprArgs[0];\n        if (arg.type !== \"NumberLiteral\" || arg.value !== 1) {\n          throw new CodegenError(\n            `.flat() only supports depth=1 (the default). MongoDB has no recursive flatten primitive.`,\n            callPos,\n          );\n        }\n      }\n      return { $reduce: { input: genObj, initialValue: [], in: { $concatArrays: [\"$$value\", \"$$this\"] } } };\n    }\n    case \"flatMap\": {\n      const lambda = requireLambda(exprArgsOnly(args, \"flatMap\"), \"flatMap\", callPos);\n      const iter = arrayIterInput(lambda, genObj, ctx, \"flatMap\");\n      return {\n        $reduce: {\n          input: { $map: { input: iter.input, as: iter.asName, in: iter.wrap(_generate(lambda.body, iter.bodyCtx)) } },\n          initialValue: [],\n          in: { $concatArrays: [\"$$value\", \"$$this\"] },\n        },\n      };\n    }\n\n    // \u2500\u2500 Array methods (lambda) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    case \"map\": {\n      const lambda = requireLambda(exprArgsOnly(args, \"map\"), \"map\", callPos);\n      const iter = arrayIterInput(lambda, genObj, ctx, \"map\");\n      return { $map: { input: iter.input, as: iter.asName, in: iter.wrap(_generate(lambda.body, iter.bodyCtx)) } };\n    }\n    case \"filter\": {\n      const lambda = requireLambda(exprArgsOnly(args, \"filter\"), \"filter\", callPos);\n      const iter = arrayIterInput(lambda, genObj, ctx, \"filter\");\n      const cond = iter.wrap(jsBoolIfNeeded(lambda.body, _generate(lambda.body, iter.bodyCtx)));\n      if (lambda.params.length <= 1) {\n        return { $filter: { input: iter.input, as: iter.asName, cond } };\n      }\n      // 2-param: filter the (index, element) pairs, then project back to elements.\n      return {\n        $map: {\n          input: { $filter: { input: iter.input, as: iter.asName, cond } },\n          as: \"jsmqlPair\",\n          in: { $arrayElemAt: [\"$$jsmqlPair\", 1] },\n        },\n      };\n    }\n    case \"find\": {\n      const lambda = requireLambda(exprArgsOnly(args, \"find\"), \"find\", callPos);\n      const iter = arrayIterInput(lambda, genObj, ctx, \"find\");\n      const cond = iter.wrap(jsBoolIfNeeded(lambda.body, _generate(lambda.body, iter.bodyCtx)));\n      if (lambda.params.length <= 1) {\n        return { $arrayElemAt: [{ $filter: { input: iter.input, as: iter.asName, cond } }, 0] };\n      }\n      // 2-param: find first matching pair, then extract its element.\n      return { $arrayElemAt: [{ $arrayElemAt: [{ $filter: { input: iter.input, as: iter.asName, cond } }, 0] }, 1] };\n    }\n    case \"some\": {\n      const lambda = requireLambda(exprArgsOnly(args, \"some\"), \"some\", callPos);\n      const iter = arrayIterInput(lambda, genObj, ctx, \"some\");\n      return {\n        $anyElementTrue: {\n          $map: {\n            input: iter.input,\n            as: iter.asName,\n            in: iter.wrap(jsBoolIfNeeded(lambda.body, _generate(lambda.body, iter.bodyCtx))),\n          },\n        },\n      };\n    }\n    case \"every\": {\n      const lambda = requireLambda(exprArgsOnly(args, \"every\"), \"every\", callPos);\n      const iter = arrayIterInput(lambda, genObj, ctx, \"every\");\n      return {\n        $allElementsTrue: {\n          $map: {\n            input: iter.input,\n            as: iter.asName,\n            in: iter.wrap(jsBoolIfNeeded(lambda.body, _generate(lambda.body, iter.bodyCtx))),\n          },\n        },\n      };\n    }\n    case \"reduce\":\n    case \"reduceRight\": {\n      const exprArgs = exprArgsOnly(args, method);\n      checkArity(method, { sig: \"lambda, initialValue\", exact: 2 }, exprArgs.length, callPos);\n      const lambda = requireLambda(exprArgs, method, callPos);\n      if (lambda.params.length < 2 || lambda.params.length > 3) {\n        throw new CodegenError(\n          `.${method}() lambda must have 2 or 3 parameters (accumulator, element[, index])`,\n          callPos,\n        );\n      }\n      // Narrow the accumulator's type when initialValue and body agree on a\n      // compound type. `$$value` after iteration i \u2265 1 is the body's return\n      // from iteration i-1, not the initialValue \u2014 so narrowing on the initial\n      // alone would be unsound (`reduce((a,x)=>x.foo, {})` keeps the cond\n      // because `a` becomes `x.foo` after the first step). When both agree the\n      // type is invariant across iterations; the IndexAccess case reads this\n      // to skip the runtime $isArray dispatch.\n      const accType: \"object\" | \"array\" | undefined =\n        isObjectProducing(exprArgs[1]) && isObjectProducing(lambda.body)\n          ? \"object\"\n          : isArrayProducing(exprArgs[1]) && isArrayProducing(lambda.body)\n            ? \"array\"\n            : undefined;\n      const nextBindingTypes = new Map(ctx.bindingTypes ?? []);\n      if (accType) nextBindingTypes.set(lambda.params[0], accType);\n      else nextBindingTypes.delete(lambda.params[0]);\n      const has3 = lambda.params.length === 3;\n      // 2-param: acc \u2192 value, element \u2192 this (status quo).\n      // 3-param: acc \u2192 value still, but element + index come from $$this being\n      // an (index, element) pair \u2014 body wraps in $let to expose both names.\n      const reduceCtx: GenerateCtx = {\n        lambdaParams: new Set([...ctx.lambdaParams, ...lambda.params]),\n        reduceRemap: has3\n          ? new Map([[lambda.params[0], \"value\"]])\n          : new Map([\n              [lambda.params[0], \"value\"],\n              [lambda.params[1], \"this\"],\n            ]),\n        pipelineLets: ctx.pipelineLets,\n        droppedLets: ctx.droppedLets,\n        bindingTypes: nextBindingTypes,\n      };\n      const baseBody = _generate(lambda.body, reduceCtx);\n      const inExpr = has3\n        ? {\n            $let: {\n              vars: {\n                [lambda.params[1]]: { $arrayElemAt: [\"$$this\", 1] },\n                [lambda.params[2]]: { $arrayElemAt: [\"$$this\", 0] },\n              },\n              in: baseBody,\n            },\n          }\n        : baseBody;\n      // reduceRight: reverse the input (or the zipped pairs) so iteration runs\n      // right-to-left. The zip happens BEFORE the reverse so each pair's index\n      // still reflects the original array position (matching JS).\n      let input: unknown = genObj;\n      if (has3) {\n        input = { $zip: { inputs: [{ $range: [0, { $size: genObj }] }, genObj] } };\n      }\n      if (method === \"reduceRight\") {\n        input = { $reverseArray: input };\n      }\n      return { $reduce: { input, initialValue: _generate(exprArgs[1], ctx), in: inExpr } };\n    }\n\n    // \u2500\u2500 Date methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    case \"getFullYear\":\n      return { $year: genObj };\n    case \"getMonth\":\n      // 0-based: MongoDB $month is 1-based\n      return { $subtract: [{ $month: genObj }, 1] };\n    case \"getDate\":\n      return { $dayOfMonth: genObj };\n    case \"getDay\":\n      // 0-based: MongoDB $dayOfWeek is 1-based (Sunday=1)\n      return { $subtract: [{ $dayOfWeek: genObj }, 1] };\n    case \"getHours\":\n      return { $hour: genObj };\n    case \"getMinutes\":\n      return { $minute: genObj };\n    case \"getSeconds\":\n      return { $second: genObj };\n    case \"getMilliseconds\":\n      return { $millisecond: genObj };\n    case \"getTime\":\n      // Match JS: ms since epoch\n      return { $toLong: genObj };\n    case \"toISOString\":\n      return { $dateToString: { date: genObj, format: \"%Y-%m-%dT%H:%M:%S.%LZ\" } };\n\n    // \u2500\u2500 DX shims: mutating Array methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    // These all mutate the receiver in JavaScript. In expression position\n    // jsmql is immutable, so we surface a tailored \"use the immutable\n    // equivalent\" message. At statement position (a top-level pipeline\n    // statement on a field-path receiver), `tryRewriteMutatorCall` rewrites\n    // the call to `$.<field> = $.<field>.<immutable>(...)` before codegen\n    // sees it \u2014 so reaching these throws means the user used a mutator in\n    // expression position.\n    case \"sort\":\n      throw new CodegenError(\n        `.sort() mutates the array in JavaScript. In expression position, use '.toSorted()' \u2014 or call it at statement position (top-level on a '$.<field>' receiver) to mutate the field.`,\n        callPos,\n      );\n    case \"reverse\":\n      throw new CodegenError(\n        `.reverse() mutates the array in JavaScript. In expression position, use '.toReversed()' \u2014 or call it at statement position (top-level on a '$.<field>' receiver) to mutate the field.`,\n        callPos,\n      );\n    case \"splice\":\n      throw new CodegenError(\n        `.splice() mutates the array in JavaScript. In expression position, use '.toSpliced(start, deleteCount, ...items)' \u2014 or call it at statement position (top-level on a '$.<field>' receiver) to mutate the field.`,\n        callPos,\n      );\n    case \"push\":\n      throw new CodegenError(\n        `.push() mutates the array in JavaScript. In expression position, use '.concat(x)' or spread '[...arr, x]' \u2014 or call it at statement position (top-level on a '$.<field>' receiver) to mutate the field.`,\n        callPos,\n      );\n    case \"pop\":\n      throw new CodegenError(\n        `.pop() mutates the array in JavaScript. In expression position, use '.at(-1)' to read the last element or '.slice(0, -1)' for everything-but-last \u2014 or call it at statement position (top-level on a '$.<field>' receiver) to drop the last element.`,\n        callPos,\n      );\n    case \"shift\":\n      throw new CodegenError(\n        `.shift() mutates the array in JavaScript. In expression position, use '.at(0)' to read the first element or '.slice(1)' for everything-but-first \u2014 or call it at statement position (top-level on a '$.<field>' receiver) to drop the first element.`,\n        callPos,\n      );\n    case \"unshift\":\n      throw new CodegenError(\n        `.unshift() mutates the array in JavaScript. In expression position, use '.concat()' with the new items first or spread '[...newItems, ...arr]' \u2014 or call it at statement position (top-level on a '$.<field>' receiver) to prepend in place.`,\n        callPos,\n      );\n    case \"fill\":\n      throw new CodegenError(\n        `.fill() mutates the array in JavaScript. In expression position there is no direct immutable replacement (build from a $range or pass a pre-filled array as a parameter) \u2014 or call it at statement position (top-level on a '$.<field>' receiver) to fill the field in place.`,\n        callPos,\n      );\n    case \"copyWithin\":\n      throw new CodegenError(\n        `.copyWithin() mutates the array in JavaScript; jsmql expressions are immutable. Call it at statement position (top-level on a '$.<field>' receiver) to copy-within the field in place, or compose '.slice()' calls with '$concatArrays' for an inline expression.`,\n        callPos,\n      );\n\n    // \u2500\u2500 DX shims: iterator / void / locale methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    // None of these have a sensible lowering to an MQL expression. Throw a\n    // pointed error explaining why, with a workaround when one exists.\n    case \"forEach\":\n      throw new CodegenError(\n        `.forEach() returns undefined in JavaScript; jsmql expressions must produce a value. Use '.map(...)' to transform, or move side-effecting work outside the query.`,\n        callPos,\n      );\n    case \"entries\":\n      throw new CodegenError(\n        `.entries() returns an iterator in JavaScript and has no MongoDB equivalent. Use '.map((v, i) => [i, v])' if you want [index, value] pairs as an array.`,\n        callPos,\n      );\n    case \"keys\":\n      throw new CodegenError(\n        `.keys() returns an iterator in JavaScript and has no MongoDB equivalent. Use '$op($range, 0, $op($size, arr))' if you want the index array.`,\n        callPos,\n      );\n    case \"values\":\n      throw new CodegenError(\n        `.values() returns an iterator in JavaScript and has no MongoDB equivalent. The array itself is already the value sequence \u2014 use it directly.`,\n        callPos,\n      );\n    case \"toLocaleString\":\n      throw new CodegenError(\n        `.toLocaleString() is locale-dependent and isn't expressible as a MongoDB expression. Use '.join(...)' with explicit formatting, or '$dateToString' for dates.`,\n        callPos,\n      );\n\n    default: {\n      const hint = didYouMean(method, KNOWN_METHODS);\n      throw new CodegenError(`Unknown method '.${method}()'.${hint}`, callPos);\n    }\n  }\n}\n\n/** True for `-N` literal expressions in either AST shape (`NumberLiteral(-N)` or\n *  `UnaryExpr(-, NumberLiteral(N))`). Used by `.toSpliced` / `.with` to reject\n *  negative literals at compile time \u2014 MongoDB's `$slice` position/length args\n *  are non-negative and a runtime check would surprise users with confusing MQL. */\nfunction isNegativeLiteral(e: Expr): boolean {\n  if (e.type === \"NumberLiteral\") return e.value < 0;\n  if (e.type === \"UnaryExpr\" && e.op === \"-\" && e.operand.type === \"NumberLiteral\") {\n    return e.operand.value > 0;\n  }\n  return false;\n}\n\n/**\n * Lower a callback's input shape so the body can reference `(element, index)` \u2014\n * the JS callback signature for `.map`, `.filter`, `.find`, `.findLast`,\n * `.some`, `.every`, `.flatMap` (matching MDN).\n *\n * - 1-param `x => \u2026`: status quo. `as` is the user's name; the body's `$$x` is\n *   bound directly by `$map` / `$filter`.\n * - 2-param `(x, i) => \u2026`: iterate over `$zip([$range(0..size), arr])` so each\n *   element is paired with its index. `as` becomes a synthetic `jsmqlPair`; a\n *   `$let` wrapper rebinds the user's names to the pair components. Picking a\n *   synthetic name (rather than reusing one of the user's params) keeps the\n *   shape uniform and avoids per-method collision checks.\n * - \u22653 params: rejected. The third `array` argument from JS would mean leaking\n *   the receiver into every iteration, which has no real use case.\n */\nfunction arrayIterInput(\n  lambda: { params: string[]; body: Expr; pos: number },\n  genObj: unknown,\n  ctx: GenerateCtx,\n  method: string,\n): { input: unknown; asName: string; bodyCtx: GenerateCtx; wrap: (body: unknown) => unknown } {\n  const params = lambda.params;\n  if (params.length >= 3) {\n    throw new CodegenError(\n      `.${method}() callbacks take at most 2 parameters (element, index); the third 'array' argument isn't supported. Reference the receiver directly instead.`,\n      lambda.pos,\n    );\n  }\n  if (params.length <= 1) {\n    return { input: genObj, asName: params[0] ?? \"v\", bodyCtx: extendCtx(ctx, params), wrap: (body) => body };\n  }\n  return {\n    input: { $zip: { inputs: [{ $range: [0, { $size: genObj }] }, genObj] } },\n    asName: \"jsmqlPair\",\n    bodyCtx: extendCtx(ctx, params),\n    wrap: (body) => ({\n      $let: {\n        vars: { [params[0]]: { $arrayElemAt: [\"$$jsmqlPair\", 1] }, [params[1]]: { $arrayElemAt: [\"$$jsmqlPair\", 0] } },\n        in: body,\n      },\n    }),\n  };\n}\n\n/**\n * Translate a `.toSorted(keyFn)` / `.sort(keyFn)` callback into the `sortBy`\n * value MongoDB's `$sortArray` expects.\n *\n * Supported callback shapes (the key-function form):\n *   - `x => x.path` \u2192 `{ \"path\": 1 }`            (ascending, dotted nested paths welcome)\n *   - `x => -x.path` \u2192 `{ \"path\": -1 }`          (descending, unary `-` only)\n *\n * Everything else \u2014 comparator-style `(a, b) => \u2026`, arithmetic on the key,\n * computed indices, 0-param or \u22652-param arrows \u2014 is rejected with a pointer at\n * the `$op($sortArray, { input, sortBy })` escape hatch.\n */\nfunction lambdaToSortBy(arg: Expr, method: string): Record<string, 1 | -1> {\n  if (arg.type !== \"Lambda\") {\n    throw new CodegenError(\n      `.${method}() supports 0 or 1 arguments \u2014 an optional key function 'x => x.path' or 'x => -x.path'. For comparator-style sorts use $op($sortArray, { input, sortBy }).`,\n      arg.pos,\n    );\n  }\n  if (arg.body === undefined) {\n    throw new CodegenError(\n      `.${method}() does not accept a block-body arrow \u2014 pass an expression-body key function like 'x => x.field'.`,\n      arg.pos,\n    );\n  }\n  if (arg.params.length !== 1) {\n    throw new CodegenError(\n      `.${method}() key function takes exactly 1 parameter ('x => x.field'). For comparator-style sorts use $op($sortArray, { input, sortBy }).`,\n      arg.pos,\n    );\n  }\n  const param = arg.params[0];\n  let body = arg.body;\n  let direction: 1 | -1 = 1;\n  if (body.type === \"UnaryExpr\" && body.op === \"-\") {\n    direction = -1;\n    body = body.operand;\n  }\n  const path = paramKeyPath(body, param);\n  if (path === null) {\n    throw new CodegenError(\n      `.${method}() key function body must be '${param}.<field>' (optionally negated). For more complex sort criteria use $op($sortArray, { input, sortBy }).`,\n      arg.body.pos,\n    );\n  }\n  return { [path]: direction };\n}\n\n/**\n * If `expr` is a `MemberAccess` chain rooted at `ParamRef(param)`, return the\n * dotted key path (e.g. `MemberAccess(MemberAccess(ParamRef(\"x\"), \"user\"), \"name\")`\n * with `param = \"x\"` \u2192 `\"user.name\"`). Otherwise null.\n */\nfunction paramKeyPath(expr: Expr, param: string): string | null {\n  if (expr.type === \"ParamRef\" && expr.name === param) {\n    // `x => x` \u2014 sort by self isn't a valid sortBy key (an empty object key).\n    return null;\n  }\n  if (expr.type === \"MemberAccess\") {\n    const base = paramKeyPath(expr.object, param);\n    if (expr.object.type === \"ParamRef\" && expr.object.name === param) {\n      return expr.member;\n    }\n    if (base !== null) return `${base}.${expr.member}`;\n  }\n  return null;\n}\n\n// \u2500\u2500 Mutating-method rewrite (statement-position desugar) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// In JavaScript the array mutators (`.sort`, `.reverse`, `.push`, `.pop`,\n// `.shift`, `.unshift`, `.splice`, `.fill`) modify the receiver in place and\n// return either the array itself or the removed element(s). MQL pipelines are\n// declaratively immutable, so we surface these as `$set` stages when \u2014 and\n// only when \u2014 the call appears at statement position with a writable\n// field-path receiver. The rewrite materialises a synthetic `AssignExpr`\n// (`$.<field> = $.<field>.<immutable equivalent>(...)`) and hands it to the\n// existing UpdateOp coalescer, so chained mutations on the same field\n// compose through the same read-after-write logic explicit `=` already uses.\n//\n// Expression-position calls (anywhere inside a larger expression, sub-pipeline,\n// `$match` body, etc.) and statement-position calls on non-field-path\n// receivers fall through to the dedicated throws in `generateMethodCall` \u2014\n// each one names the immutable variant the user should reach for instead.\n\nconst MUTATING_ARRAY_METHODS: ReadonlySet<string> = new Set([\n  \"sort\",\n  \"reverse\",\n  \"push\",\n  \"pop\",\n  \"shift\",\n  \"unshift\",\n  \"splice\",\n  \"fill\",\n  \"copyWithin\",\n]);\n\n/**\n * Predicate: can `target` appear on the LHS of an `AssignExpr`? Mirrors the\n * parser's constraint for `$.<path> = <expr>` \u2014 a `FieldRef` with a non-empty\n * path, or a `MemberAccess` chain rooted at one. Bare `$` (path `\"\"`) is the\n * `$replaceWith` sugar, not an assignable field.\n */\nexport function isWritableFieldPath(expr: Expr): boolean {\n  if (expr.type === \"FieldRef\") return expr.path !== \"\";\n  if (expr.type === \"MemberAccess\") return isWritableFieldPath(expr.object);\n  return false;\n}\n\nexport type MutatorRewrite = { kind: \"rewrite\"; assign: AssignExpr } | { kind: \"passthrough\" };\n\n/**\n * If `expr` is a mutating array method on a writable field-path receiver,\n * return the synthesized `$.<field> = <immutable RHS>` `AssignExpr`. The RHS\n * AST is built from existing Expr node types so it flows through normal\n * codegen \u2014 there is no per-mutator branch in the lowering path.\n */\nexport function tryRewriteMutatorCall(expr: Expr): MutatorRewrite {\n  if (expr.type !== \"MethodCall\") return { kind: \"passthrough\" };\n  if (!MUTATING_ARRAY_METHODS.has(expr.method)) return { kind: \"passthrough\" };\n  if (!isWritableFieldPath(expr.object)) return { kind: \"passthrough\" };\n  const value = buildMutatorRhs(expr.method, expr.object, expr.args, expr.pos);\n  return { kind: \"rewrite\", assign: { type: \"AssignExpr\", target: expr.object, value, pos: expr.pos } };\n}\n\nfunction buildMutatorRhs(method: string, object: Expr, args: CallArg[], pos: number): Expr {\n  switch (method) {\n    case \"sort\":\n      // Delegate to the existing `.toSorted` lowering \u2014 including 0-arg ascending\n      // form and 1-arg key-function form. The args list is forwarded as-is.\n      return { type: \"MethodCall\", object, method: \"toSorted\", args, pos };\n    case \"reverse\":\n      checkArity(\"reverse\", { sig: \"\", none: true }, args.length, pos);\n      return { type: \"MethodCall\", object, method: \"toReversed\", args: [], pos };\n    case \"splice\":\n      return { type: \"MethodCall\", object, method: \"toSpliced\", args, pos };\n    case \"push\": {\n      // `arr.push(a, b)` \u2192 `arr.concat([a, b])`-style, but `.concat` flattens\n      // arrays one level (JS spec), while `.push` does not. Emit\n      // `$concatArrays: [arr, [a, b]]` directly so an array argument is added\n      // as a single element, matching JS.\n      const items: ArrayElement[] = args.map((a) => a as ArrayElement);\n      const itemsArr: Expr = { type: \"ArrayLiteral\", elements: items, pos };\n      return { type: \"OperatorCall\", name: \"$concatArrays\", style: \"positional\", args: [object, itemsArr], pos };\n    }\n    case \"unshift\": {\n      const items: ArrayElement[] = args.map((a) => a as ArrayElement);\n      const itemsArr: Expr = { type: \"ArrayLiteral\", elements: items, pos };\n      return { type: \"OperatorCall\", name: \"$concatArrays\", style: \"positional\", args: [itemsArr, object], pos };\n    }\n    case \"pop\": {\n      checkArity(\"pop\", { sig: \"\", none: true }, args.length, pos);\n      // `arr.slice(0, max(0, size - 1))` \u2014 everything-but-last with a clamp so\n      // an empty input yields an empty output instead of `$slice([], 0, -1)`.\n      const sizeExpr: Expr = mkOpCall(\"$size\", [object], pos);\n      const minus1: Expr = { type: \"BinaryExpr\", op: \"-\", left: sizeExpr, right: mkNumber(1, pos), pos };\n      const clamped: Expr = mkOpCall(\"$max\", [mkNumber(0, pos), minus1], pos);\n      return mkOpCall(\"$slice\", [object, mkNumber(0, pos), clamped], pos);\n    }\n    case \"shift\": {\n      checkArity(\"shift\", { sig: \"\", none: true }, args.length, pos);\n      // `$slice: [arr, 1, $size(arr)]` \u2014 start at index 1 and take everything\n      // remaining. MongoDB clamps `len` to what's actually available, so an\n      // empty input yields an empty output.\n      const sizeExpr: Expr = mkOpCall(\"$size\", [object], pos);\n      return mkOpCall(\"$slice\", [object, mkNumber(1, pos), sizeExpr], pos);\n    }\n    case \"fill\":\n      return buildFillRhs(object, args, pos);\n    case \"copyWithin\":\n      return buildCopyWithinRhs(object, args, pos);\n  }\n  return internalError(`tryRewriteMutatorCall: unhandled method '${method}'`, pos);\n}\n\n/**\n * `arr.copyWithin(target, start, end?)` \u2014 JS in-place sequence copy. We lower\n * to a recomposition: take the prefix [0, target), splice in arr[start, end),\n * then the suffix starting at target + len. The suffix len is the original\n * size minus (target + len), clamped to non-negative.\n *\n * We accept non-negative integer literals only (no JS negative-indexing or\n * runtime values) \u2014 consistent with `.slice` / `.toSpliced` / `.fill` on\n * statement-position mutators. Two-arg form (`target, start`) treats `end`\n * as the array's `$size` at runtime.\n */\nfunction buildCopyWithinRhs(object: Expr, args: CallArg[], pos: number): Expr {\n  checkArity(\"copyWithin\", { sig: \"target, start[, end]\", allowed: [2, 3] }, args.length, pos);\n  const lits = args.map((a) => {\n    if (a.type === \"SpreadElement\") {\n      throw new CodegenError(`.copyWithin(target, start[, end]) does not accept spread arguments.`, a.pos);\n    }\n    if (a.type !== \"NumberLiteral\" || !Number.isInteger(a.value) || a.value < 0) {\n      throw new CodegenError(\n        `.copyWithin(target, start[, end]) requires non-negative integer literals; got '${a.type}'. ` +\n          `Computed or negative arguments aren't supported \u2014 JS's negative-indexing isn't representable here.`,\n        a.pos,\n      );\n    }\n    return a.value;\n  });\n  const target = lits[0];\n  const start = lits[1];\n  const endLit: number | null = lits.length === 3 ? lits[2] : null;\n  // len = end - start (constant if end is literal; $subtract: [size, start] otherwise)\n  const lenExpr: Expr =\n    endLit !== null\n      ? mkNumber(Math.max(0, endLit - start), pos)\n      : mkOpCall(\n          \"$max\",\n          [mkNumber(0, pos), mkOpCall(\"$subtract\", [mkOpCall(\"$size\", [object], pos), mkNumber(start, pos)], pos)],\n          pos,\n        );\n  // Suffix start position: target + len (constant if literal-end, else $add)\n  const suffixStartExpr: Expr =\n    endLit !== null\n      ? mkNumber(target + Math.max(0, endLit - start), pos)\n      : mkOpCall(\"$add\", [mkNumber(target, pos), lenExpr], pos);\n  // Suffix length: $max(0, $size(arr) - suffixStart)\n  const suffixLenExpr: Expr = mkOpCall(\n    \"$max\",\n    [mkNumber(0, pos), mkOpCall(\"$subtract\", [mkOpCall(\"$size\", [object], pos), suffixStartExpr], pos)],\n    pos,\n  );\n  // $concatArrays: [prefix, copied, suffix]\n  const prefix = mkOpCall(\"$slice\", [object, mkNumber(0, pos), mkNumber(target, pos)], pos);\n  const copied = mkOpCall(\"$slice\", [object, mkNumber(start, pos), lenExpr], pos);\n  const suffix = mkOpCall(\"$slice\", [object, suffixStartExpr, suffixLenExpr], pos);\n  return mkOpCall(\"$concatArrays\", [prefix, copied, suffix], pos);\n}\n\nfunction mkOpCall(name: string, args: Expr[], pos: number): Expr {\n  return { type: \"OperatorCall\", name, style: \"positional\", args, pos };\n}\n\nfunction mkNumber(value: number, pos: number): Expr {\n  return { type: \"NumberLiteral\", value, pos };\n}\n\n/**\n * `.fill(v[, start[, end]])` at statement position.\n *\n * Lower to an IIFE that binds the normalised start/end once, then maps over\n * the array swapping in `v` for indices in `[s0, e0)` and keeping the original\n * element elsewhere:\n *\n *   ((s0, e0) => arr.map((x, i) => (i >= s0 && i < e0) ? v : x))(\n *     <normalised start>, <normalised end>,\n *   )\n *\n * Normalisation matches JS:\n *   - `start` undefined  \u21D2 0\n *   - `start < 0`        \u21D2 max(0, size + start)\n *   - `start >= 0`       \u21D2 start\n *   - `end` undefined    \u21D2 size\n *   - `end < 0`          \u21D2 max(0, size + end)\n *   - `end >= 0`         \u21D2 end\n */\nfunction buildFillRhs(object: Expr, args: CallArg[], pos: number): Expr {\n  checkArity(\"fill\", { sig: \"value[, start[, end]]\", allowed: [1, 2, 3] }, args.length, pos);\n  const exprArgs: Expr[] = [];\n  for (const a of args) {\n    if (a.type === \"SpreadElement\") {\n      throw new CodegenError(`Spread (...) is not supported as an argument to .fill()`, a.pos);\n    }\n    exprArgs.push(a);\n  }\n  const v = exprArgs[0];\n  const startArg: Expr | undefined = exprArgs[1];\n  const endArg: Expr | undefined = exprArgs[2];\n\n  const zero = mkNumber(0, pos);\n\n  // Compile-time fast path: when `start` and `end` are both omitted, every\n  // element becomes `v`. Skip the IIFE and the index plumbing entirely.\n  if (startArg === undefined && endArg === undefined) {\n    const unusedAndV: Expr = { type: \"Lambda\", params: [\"__jsmql_unused\"], body: v, pos };\n    return { type: \"MethodCall\", object, method: \"map\", args: [unusedAndV], pos };\n  }\n\n  const sizeOf = (): Expr => mkOpCall(\"$size\", [object], pos);\n  const normalize = (e: Expr | undefined, defaultIfUndef: () => Expr): Expr => {\n    if (e === undefined) return defaultIfUndef();\n    // Compile-time fast path: a non-negative number literal needs no\n    // normalisation \u2014 pass it through verbatim. Avoids emitting a runtime\n    // `$cond: [{ $lt: [n, 0] }, \u2026, n]` whose test is statically false.\n    if (e.type === \"NumberLiteral\" && e.value >= 0) return e;\n    // `e < 0 ? max(0, size + e) : e`\n    const isNeg: Expr = { type: \"BinaryExpr\", op: \"<\", left: e, right: zero, pos };\n    const fromTail: Expr = { type: \"BinaryExpr\", op: \"+\", left: sizeOf(), right: e, pos };\n    const clamped = mkOpCall(\"$max\", [zero, fromTail], pos);\n    return { type: \"TernaryExpr\", condition: isNeg, consequent: clamped, alternate: e, pos };\n  };\n\n  const s0Init = normalize(startArg, () => zero);\n  const e0Init = normalize(endArg, () => sizeOf());\n\n  // Inner map body: `(i >= __jsmql_s0 && i < __jsmql_e0) ? v : x`.\n  const sRef: Expr = { type: \"ParamRef\", name: \"__jsmql_s0\", pos };\n  const eRef: Expr = { type: \"ParamRef\", name: \"__jsmql_e0\", pos };\n  const xRef: Expr = { type: \"ParamRef\", name: \"x\", pos };\n  const iRef: Expr = { type: \"ParamRef\", name: \"i\", pos };\n  const condition: Expr = {\n    type: \"BinaryExpr\",\n    op: \"&&\",\n    left: { type: \"BinaryExpr\", op: \">=\", left: iRef, right: sRef, pos },\n    right: { type: \"BinaryExpr\", op: \"<\", left: iRef, right: eRef, pos },\n    pos,\n  };\n  const mapBody: Expr = { type: \"TernaryExpr\", condition, consequent: v, alternate: xRef, pos };\n  const mapLambda: Expr = { type: \"Lambda\", params: [\"x\", \"i\"], body: mapBody, pos };\n  const mapCall: Expr = { type: \"MethodCall\", object, method: \"map\", args: [mapLambda], pos };\n\n  const iifeCallee: Expr = { type: \"Lambda\", params: [\"__jsmql_s0\", \"__jsmql_e0\"], body: mapCall, pos };\n  return { type: \"CallExpression\", callee: iifeCallee, args: [s0Init, e0Init], pos };\n}\n\n// Every recognised method name, used to power \"did you mean?\" suggestions on\n// unknown methods \u2014 derived from the METHODS registry so adding a method is a\n// single entry there (no separate list to keep in sync).\nconst KNOWN_METHODS: ReadonlySet<string> = new Set(Object.keys(METHODS));\n\n/**\n * Most methods can't take spread args \u2014 only variadic ones (concat). This helper\n * unwraps a CallArg list to a plain Expr list and rejects spreads with a clear error.\n */\nfunction exprArgsOnly(args: CallArg[], method: string): Expr[] {\n  return args.map((a) => {\n    if (a.type === \"SpreadElement\") {\n      throw new CodegenError(`Spread (...) is not supported as an argument to .${method}()`, a.pos);\n    }\n    return a;\n  });\n}\n\n/**\n * Argument-count spec for a method/static call. Exactly one of\n * `exact` / `allowed` / `atLeast` / `none` is set. `sig` is the parameter\n * signature shown in the error \u2014 e.g. `\"start[, count]\"` renders as\n * `.substr(start[, count])`; `\"\"` renders the bare `.toReversed()`.\n */\ntype Arity = { sig: string; exact?: number; allowed?: readonly number[]; atLeast?: number; none?: true };\n\n/**\n * The single place every argument-count error is worded, so the surface stays\n * consistent (see the error-consistency rules in CLAUDE.md). Validates `count`\n * against `spec` and throws `<prefix><method>(<sig>) <quantity-clause>, got <N>`\n * on mismatch \u2014 `.charAt(index) requires exactly 1 argument, got 0`,\n * `.slice(start[, end]) requires 0, 1, or 2 arguments, got 3`,\n * `Math.hypot(...values) requires at least 1 argument, got 0`. The trailing\n * `, got <N>` tells the user exactly what they passed. The caller passes the\n * count it validates (`exprArgs.length` for most; raw `args.length` for the few\n * that count spread args). `prefix` is `\".\"` for instance methods (the default)\n * or `\"Math.\"` / `\"Object.\"` / `\"Set.\"` / `\"regex.\"` for the static families.\n */\nfunction checkArity(method: string, spec: Arity, count: number, callPos: number, prefix: string = \".\"): void {\n  const ok =\n    spec.none !== undefined\n      ? count === 0\n      : spec.exact !== undefined\n        ? count === spec.exact\n        : spec.allowed !== undefined\n          ? spec.allowed.includes(count)\n          : count >= spec.atLeast!;\n  if (ok) return;\n  let quantity: string;\n  if (spec.none !== undefined) {\n    quantity = \"takes no arguments\";\n  } else if (spec.exact !== undefined) {\n    quantity = `requires exactly ${spec.exact} argument${spec.exact === 1 ? \"\" : \"s\"}`;\n  } else if (spec.allowed !== undefined) {\n    quantity = `requires ${formatCountList(spec.allowed)} arguments`;\n  } else {\n    quantity = `requires at least ${spec.atLeast} argument${spec.atLeast === 1 ? \"\" : \"s\"}`;\n  }\n  throw new CodegenError(`${prefix}${method}(${spec.sig}) ${quantity}, got ${count}`, callPos);\n}\n\n/** Render an allowed-count list the way the messages read: `[1,2]` \u2192 \"1 or 2\",\n *  `[0,1,2]` \u2192 \"0, 1, or 2\". */\nfunction formatCountList(ns: readonly number[]): string {\n  if (ns.length === 2) return `${ns[0]} or ${ns[1]}`;\n  return `${ns.slice(0, -1).join(\", \")}, or ${ns[ns.length - 1]}`;\n}\n\nfunction requireLambda(\n  args: Expr[],\n  method: string,\n  callerPos: number,\n): { type: \"Lambda\"; params: string[]; body: Expr; pos: number } {\n  const first = args[0];\n  // Bare type-cast callback: `.filter(Boolean)` desugars to `.filter(v => Boolean(v))`.\n  if (first?.type === \"TypeCastRef\") {\n    return {\n      type: \"Lambda\",\n      params: [\"v\"],\n      body: {\n        type: \"TypeCast\",\n        cast: first.cast,\n        arg: { type: \"ParamRef\", name: \"v\", pos: first.pos },\n        pos: first.pos,\n      },\n      pos: first.pos,\n    };\n  }\n  // Bare unary-Math callback: `.map(Math.floor)` desugars to `.map(v => Math.floor(v))`.\n  if (first?.type === \"MathCallRef\") {\n    return {\n      type: \"Lambda\",\n      params: [\"v\"],\n      body: {\n        type: \"MathCall\",\n        method: first.method,\n        args: [{ type: \"ParamRef\", name: \"v\", pos: first.pos }],\n        pos: first.pos,\n      },\n      pos: first.pos,\n    };\n  }\n  if (!first || first.type !== \"Lambda\") {\n    throw new CodegenError(\n      `.${method}() requires a lambda as its first argument, e.g. x => x > 0`,\n      first?.pos ?? callerPos,\n    );\n  }\n  if (first.body === undefined) {\n    throw new CodegenError(\n      `.${method}() does not accept a block-body arrow \u2014 only '$$$.<coll>.find/filter(...)' does. Use an expression-body arrow like \\`x => x > 0\\`.`,\n      first.pos,\n    );\n  }\n  return first as { type: \"Lambda\"; params: string[]; body: Expr; pos: number };\n}\n\n// \u2500\u2500 Call expressions (IIFE \u2192 $let) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * The only supported call form is an IIFE \u2014 a call whose callee is a lambda literal:\n *\n *   ((x, y) => $.a + x * y)(2, 3)\n *   \u2192 { $let: { vars: { x: 2, y: 3 }, in: { $add: [\"$a\", { $multiply: [\"$$x\", 3] }] } } }\n *\n * Other callees (e.g. a field reference followed by `(...)`) are not callable in MQL \u2014\n * we reject them with an error pointing at the supported forms.\n */\nfunction generateCallExpression(callee: Expr, args: CallArg[], ctx: GenerateCtx, pos: number): unknown {\n  if (callee.type !== \"Lambda\") {\n    throw new CodegenError(\n      `Direct call '(...)(args)' is only supported when the callee is an arrow function (IIFE \u2192 $let). For named operators use $opName(...); for methods use receiver.method(...).`,\n      pos,\n    );\n  }\n  if (callee.body === undefined) {\n    throw new CodegenError(\n      `IIFE callee cannot be a block-body arrow \u2014 only '$$$.<coll>.find/filter(...)' accepts block bodies.`,\n      callee.pos,\n    );\n  }\n  if (callee.params.length !== args.length) {\n    throw new CodegenError(\n      `IIFE: expected ${callee.params.length} argument(s) for params (${callee.params.join(\", \")}), got ${args.length}`,\n      pos,\n    );\n  }\n  const vars: Record<string, unknown> = {};\n  for (let i = 0; i < callee.params.length; i++) {\n    const a = args[i];\n    if (a.type === \"SpreadElement\") {\n      throw new CodegenError(`IIFE: spread arguments are not supported (use $op($let, ...) instead)`, a.pos);\n    }\n    vars[callee.params[i]] = _generate(a, ctx);\n  }\n  const bodyCtx = extendCtx(ctx, callee.params);\n  return { $let: { vars, in: _generate(callee.body, bodyCtx) } };\n}\n\n// \u2500\u2500 Type casts \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateTypeCast(cast: TypeCastOp, arg: Expr, ctx: GenerateCtx, _pos: number): unknown {\n  const val = _generate(arg, ctx);\n  switch (cast) {\n    case \"Number\":\n    case \"parseFloat\":\n      return { $toDouble: val };\n    case \"String\":\n      return { $toString: val };\n    case \"Boolean\":\n      // JS truthy/falsy semantics \u2014 see jsBool() above. Users who want the\n      // raw MongoDB $toBool can call it directly: $toBool($.x).\n      return jsBoolIfNeeded(arg, val);\n    case \"parseInt\":\n      return { $toInt: val };\n  }\n}\n\n// \u2500\u2500 Math \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateMathConst(name: MathConstant): number {\n  switch (name) {\n    case \"PI\":\n      return Math.PI;\n    case \"E\":\n      return Math.E;\n  }\n}\n\nfunction generateMathCall(method: MathMethod, args: CallArg[], ctx: GenerateCtx, pos: number): unknown {\n  switch (method) {\n    case \"abs\":\n      return { $abs: oneArg(method, args, ctx, pos) };\n    case \"ceil\":\n      return { $ceil: oneArg(method, args, ctx, pos) };\n    case \"floor\":\n      return { $floor: oneArg(method, args, ctx, pos) };\n    case \"round\":\n      return { $round: [oneArg(method, args, ctx, pos), 0] };\n    case \"sqrt\":\n      return { $sqrt: oneArg(method, args, ctx, pos) };\n    case \"exp\":\n      return { $exp: oneArg(method, args, ctx, pos) };\n    case \"log\":\n      // Math.log is natural log \u2192 $ln\n      return { $ln: oneArg(method, args, ctx, pos) };\n    case \"log2\":\n      return { $log: [oneArg(method, args, ctx, pos), 2] };\n    case \"log10\":\n      return { $log10: oneArg(method, args, ctx, pos) };\n    case \"trunc\":\n      return { $trunc: oneArg(method, args, ctx, pos) };\n    case \"sign\":\n      // JS returns -1 / 0 / 1 for negative / zero / positive \u2014 same as $cmp(x, 0)\n      return { $cmp: [oneArg(method, args, ctx, pos), 0] };\n    case \"cbrt\":\n      return { $pow: [oneArg(method, args, ctx, pos), { $divide: [1, 3] }] };\n    case \"pow\": {\n      const exprArgs = exprArgsOnly(args, \"pow\");\n      checkArity(\"pow\", { sig: \"base, exponent\", exact: 2 }, exprArgs.length, pos, \"Math.\");\n      return { $pow: [_generate(exprArgs[0], ctx), _generate(exprArgs[1], ctx)] };\n    }\n    case \"min\":\n    case \"max\": {\n      // Variadic: accept (a, b, c, ...) OR a single array OR ...spread\n      checkArity(method, { sig: \"...values\", atLeast: 1 }, args.length, pos, \"Math.\");\n      const op = method === \"min\" ? \"$min\" : \"$max\";\n      // Single non-spread arg \u2192 pass through (Mongo $min/$max accept either a value or an array)\n      if (args.length === 1 && args[0].type !== \"SpreadElement\") {\n        return { [op]: _generate(args[0], ctx) };\n      }\n      return { [op]: generateVariadicArgs(args, ctx) };\n    }\n    case \"hypot\": {\n      const exprArgs = exprArgsOnly(args, \"hypot\");\n      checkArity(\"hypot\", { sig: \"...values\", atLeast: 1 }, exprArgs.length, pos, \"Math.\");\n      const squares = exprArgs.map((a) => ({ $pow: [_generate(a, ctx), 2] }));\n      return { $sqrt: { $add: squares } };\n    }\n    case \"random\":\n      checkArity(\"random\", { sig: \"\", none: true }, args.length, pos, \"Math.\");\n      return { $rand: {} };\n    case \"sin\":\n      return { $sin: oneArg(method, args, ctx, pos) };\n    case \"cos\":\n      return { $cos: oneArg(method, args, ctx, pos) };\n    case \"tan\":\n      return { $tan: oneArg(method, args, ctx, pos) };\n    case \"asin\":\n      return { $asin: oneArg(method, args, ctx, pos) };\n    case \"acos\":\n      return { $acos: oneArg(method, args, ctx, pos) };\n    case \"atan\":\n      return { $atan: oneArg(method, args, ctx, pos) };\n    case \"atan2\": {\n      const exprArgs = exprArgsOnly(args, \"atan2\");\n      checkArity(\"atan2\", { sig: \"y, x\", exact: 2 }, exprArgs.length, pos, \"Math.\");\n      return { $atan2: [_generate(exprArgs[0], ctx), _generate(exprArgs[1], ctx)] };\n    }\n    case \"sinh\":\n      return { $sinh: oneArg(method, args, ctx, pos) };\n    case \"cosh\":\n      return { $cosh: oneArg(method, args, ctx, pos) };\n    case \"tanh\":\n      return { $tanh: oneArg(method, args, ctx, pos) };\n    case \"asinh\":\n      return { $asinh: oneArg(method, args, ctx, pos) };\n    case \"acosh\":\n      return { $acosh: oneArg(method, args, ctx, pos) };\n    case \"atanh\":\n      return { $atanh: oneArg(method, args, ctx, pos) };\n  }\n}\n\nfunction oneArg(method: MathMethod, args: CallArg[], ctx: GenerateCtx, pos: number): unknown {\n  const exprArgs = exprArgsOnly(args, method);\n  checkArity(method, { sig: \"value\", exact: 1 }, exprArgs.length, pos, \"Math.\");\n  return _generate(exprArgs[0], ctx);\n}\n\n// \u2500\u2500 Object calls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateObjectCall(method: ObjectMethod, args: CallArg[], ctx: GenerateCtx, pos: number): unknown {\n  // Helper: wrap argument with $ifNull(v, neutral) when the chain has `?.`\n  // (`$objectToArray(null)` and `$arrayToObject(null)` both error).\n  const genWith = (arg: Expr, neutral: unknown): unknown => {\n    const gen = _generate(arg, ctx);\n    return chainHasOptional(arg) ? wrapIfNull(gen, neutral) : gen;\n  };\n  switch (method) {\n    case \"keys\": {\n      const exprArgs = exprArgsOnly(args, \"Object.keys\");\n      checkArity(\"keys\", { sig: \"obj\", exact: 1 }, exprArgs.length, pos, \"Object.\");\n      return { $map: { input: { $objectToArray: genWith(exprArgs[0], {}) }, as: \"kv\", in: \"$$kv.k\" } };\n    }\n    case \"values\": {\n      const exprArgs = exprArgsOnly(args, \"Object.values\");\n      checkArity(\"values\", { sig: \"obj\", exact: 1 }, exprArgs.length, pos, \"Object.\");\n      return { $map: { input: { $objectToArray: genWith(exprArgs[0], {}) }, as: \"kv\", in: \"$$kv.v\" } };\n    }\n    case \"entries\": {\n      const exprArgs = exprArgsOnly(args, \"Object.entries\");\n      checkArity(\"entries\", { sig: \"obj\", exact: 1 }, exprArgs.length, pos, \"Object.\");\n      return { $objectToArray: genWith(exprArgs[0], {}) };\n    }\n    case \"fromEntries\": {\n      const exprArgs = exprArgsOnly(args, \"Object.fromEntries\");\n      checkArity(\"fromEntries\", { sig: \"entries\", exact: 1 }, exprArgs.length, pos, \"Object.\");\n      return { $arrayToObject: genWith(exprArgs[0], []) };\n    }\n    case \"assign\": {\n      checkArity(\"assign\", { sig: \"...sources\", atLeast: 1 }, args.length, pos, \"Object.\");\n      return { $mergeObjects: generateVariadicArgs(args, ctx) };\n    }\n    case \"groupBy\": {\n      const exprArgs = exprArgsOnly(args, \"Object.groupBy\");\n      checkArity(\"groupBy\", { sig: \"items, x => key\", exact: 2 }, exprArgs.length, pos, \"Object.\");\n      const input = exprArgs[0];\n      const lambda = exprArgs[1];\n      if (lambda.type !== \"Lambda\" || lambda.params.length !== 1) {\n        throw new CodegenError(\n          `Object.groupBy() requires a single-parameter arrow function as the discriminator`,\n          lambda.pos,\n        );\n      }\n      if (lambda.body === undefined) {\n        throw new CodegenError(\n          `Object.groupBy() does not accept a block-body arrow \u2014 only '$$$.<coll>.find/filter(...)' does.`,\n          lambda.pos,\n        );\n      }\n      // Reduce over the input. For each element, compute the discriminator key with the\n      // user's lambda param bound to $$this. Use $let to materialise the key once, then\n      // append the current element to the array under that key in the accumulator.\n      const keyCtx: GenerateCtx = {\n        lambdaParams: new Set([...ctx.lambdaParams, lambda.params[0]]),\n        reduceRemap: new Map([[lambda.params[0], \"this\"]]),\n        pipelineLets: ctx.pipelineLets,\n        droppedLets: ctx.droppedLets,\n        bindingTypes: ctx.bindingTypes,\n      };\n      const keyBody = _generate(lambda.body, keyCtx);\n      const keyExpr = isStringProducing(lambda.body) ? keyBody : { $toString: keyBody };\n      return {\n        $reduce: {\n          input: _generate(input, ctx),\n          initialValue: {},\n          in: {\n            $let: {\n              vars: { key: keyExpr },\n              in: {\n                $mergeObjects: [\n                  \"$$value\",\n                  {\n                    $arrayToObject: [\n                      [\n                        [\n                          \"$$key\",\n                          {\n                            $concatArrays: [\n                              { $ifNull: [{ $getField: { field: \"$$key\", input: \"$$value\" } }, []] },\n                              [\"$$this\"],\n                            ],\n                          },\n                        ],\n                      ],\n                    ],\n                  },\n                ],\n              },\n            },\n          },\n        },\n      };\n    }\n  }\n}\n\n// \u2500\u2500 Array.from \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * `Array.from({length: n}, (_, i) => f(i))` \u2014 the only supported form. Other\n * Array.from invocations are rejected because MQL has no general iterable-to-array\n * primitive. Compiles to `$map($range(0, n), (i) => body)` where the lambda's first\n * (element) parameter is bound to null via $let, matching JS's `Array.from({length}, ...)`\n * semantics where the element is always undefined.\n */\n/**\n * Lower `new Date(args\u2026)`:\n *   - 0 args (`new Date()`)               \u2192 `{ $toDate: \"$$NOW\" }`\n *   - 1 arg  (`new Date(ts)` / `(string)`) \u2192 `{ $toDate: <arg> }`\n *   - 2..7 args                            \u2192 `{ $dateFromParts: { year, month: +1, \u2026 } }`\n *\n * JS month indices are 0-based; MQL `$dateFromParts.month` is 1-based, so an\n * `$add: [month, 1]` is inserted (folded at compile time for literal months).\n *\n * Divergence: JS multi-arg `new Date(y, m, d, \u2026)` interprets the parts in\n * **local time** (whatever the runtime considers local); jsmql interprets\n * them as **UTC** (MQL's `$dateFromParts` default), since \"local time\" on a\n * MongoDB server is rarely what a query author wants. Use `Date.UTC(...)`\n * (or build the Date in client code and pass it via the template-tag form)\n * if the JS-local semantics matter.\n */\nfunction generateNewDate(args: Expr[], ctx: GenerateCtx): unknown {\n  if (args.length === 0) return { $toDate: \"$$NOW\" };\n  if (args.length === 1) {\n    // Peephole: `new Date(Date.UTC(y, m, d, \u2026))` is the canonical UTC-date\n    // constant idiom. Skip the `$toLong \u2192 $toDate` round-trip and emit the\n    // raw `$dateFromParts` (still UTC-anchored, just as a Date instead of ms).\n    const arg = args[0];\n    if (arg.type === \"DateUTC\") {\n      return generateDateFromParts(arg.args, ctx, \"UTC\");\n    }\n    return { $toDate: _generate(arg, ctx) };\n  }\n  return generateDateFromParts(args, ctx, /*timezone*/ null);\n}\n\n/**\n * Lower `Date.UTC(y, m, d, \u2026)`. JS returns **ms since epoch as a number**, not\n * a Date \u2014 so we wrap `$dateFromParts` (with `timezone: \"UTC\"`) in `$toLong`\n * to produce the same numeric value. The `new Date(Date.UTC(\u2026))` form gets a\n * peephole in `generateNewDate` that skips the wrap.\n */\nfunction generateDateUTC(args: Expr[], ctx: GenerateCtx): unknown {\n  return { $toLong: generateDateFromParts(args, ctx, \"UTC\") };\n}\n\n/**\n * Build a `$dateFromParts` document from a positional argument list. Used by\n * both `new Date(y, m, d, \u2026)` (no timezone) and `Date.UTC(y, m, d, \u2026)`\n * (timezone: \"UTC\"). Folds the JS-to-MQL month offset (+1) when the month\n * argument is a number literal.\n */\nfunction generateDateFromParts(args: Expr[], ctx: GenerateCtx, timezone: string | null): unknown {\n  const parts: Record<string, unknown> = { year: _generate(args[0], ctx) };\n  if (args.length >= 2) {\n    const monthAst = args[1];\n    if (monthAst.type === \"NumberLiteral\") {\n      parts.month = monthAst.value + 1;\n    } else {\n      parts.month = { $add: [_generate(monthAst, ctx), 1] };\n    }\n  }\n  const slots = [\"day\", \"hour\", \"minute\", \"second\", \"millisecond\"];\n  for (let i = 2; i < args.length && i - 2 < slots.length; i++) {\n    parts[slots[i - 2]] = _generate(args[i], ctx);\n  }\n  if (timezone !== null) parts.timezone = timezone;\n  return { $dateFromParts: parts };\n}\n\nfunction generateArrayFrom(input: Expr, mapFn: Expr | null, ctx: GenerateCtx, pos: number): unknown {\n  if (input.type !== \"ObjectLiteral\") {\n    throw new CodegenError(\n      `Array.from() only supports the {length: n} form: Array.from({length: n}, (_, i) => \u2026). For other inputs use $op($range, \u2026) or .map().`,\n      input.pos,\n    );\n  }\n  if (input.entries.length !== 1) {\n    throw new CodegenError(`Array.from({length: n}) \u2014 exactly one 'length' entry is required`, input.pos);\n  }\n  const entry = input.entries[0];\n  if (entry.type !== \"KeyValueEntry\" || entry.key.kind !== \"static\" || entry.key.name !== \"length\") {\n    throw new CodegenError(`Array.from() only supports {length: n}; saw a different object shape`, entry.pos);\n  }\n  const lengthExpr = _generate(entry.value, ctx);\n  if (mapFn === null) {\n    return { $range: [0, lengthExpr] };\n  }\n  if (mapFn.type !== \"Lambda\") {\n    throw new CodegenError(`Array.from() second argument must be an arrow function (e.g. (_, i) => i * 2)`, mapFn.pos);\n  }\n  if (mapFn.body === undefined) {\n    throw new CodegenError(\n      `Array.from() does not accept a block-body arrow \u2014 only '$$$.<coll>.find/filter(...)' does.`,\n      mapFn.pos,\n    );\n  }\n  if (mapFn.params.length !== 2) {\n    throw new CodegenError(\n      `Array.from() map function must take 2 parameters (element, index) \u2014 element is always null in the {length} form`,\n      mapFn.pos,\n    );\n  }\n  void pos;\n  const [elemParam, idxParam] = mapFn.params;\n  const bodyCtx = extendCtx(ctx, mapFn.params);\n  return {\n    $map: {\n      input: { $range: [0, lengthExpr] },\n      as: idxParam,\n      in: { $let: { vars: { [elemParam]: null }, in: _generate(mapFn.body, bodyCtx) } },\n    },\n  };\n}\n\n// \u2500\u2500 Number.* static predicates \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateNumberStatic(method: NumberStaticMethod, arg: Expr, ctx: GenerateCtx): unknown {\n  const val = _generate(arg, ctx);\n  const pos = arg.pos;\n  switch (method) {\n    case \"isInteger\":\n      // BSON has separate int/long/decimal/double types. Match JS: any numeric\n      // value with no fractional part is an integer. Long and int are always\n      // integers; double/decimal are integers iff trunc(x) === x.\n      return {\n        $cond: [\n          { $in: [{ $type: val }, [\"int\", \"long\"]] },\n          true,\n          { $cond: [{ $in: [{ $type: val }, [\"double\", \"decimal\"]] }, { $eq: [val, { $trunc: val }] }, false] },\n        ],\n      };\n    case \"isNaN\":\n      // NaN is the only IEEE 754 value where x !== x.\n      return { $ne: [val, val] };\n    case \"isFinite\":\n      // jsmql has no JS-syntax surface for \u00B1Infinity or NaN literals, so we\n      // cannot emit the obvious `{ $and: [{ $ne: [$x, Infinity] }, ...] }`.\n      // Lifting this needs a literal-Infinity/literal-NaN escape hatch \u2014 track\n      // separately. Until then, give users a concrete workaround in the error.\n      throw new CodegenError(\n        `Number.isFinite($.x) is not yet supported in jsmql [DEF-022] \u2014 there is no syntax for Infinity/NaN literals to compare against. ` +\n          `Workarounds: ` +\n          `(1) check the BSON type with $type($.x) and reject \"double\" values you know to be non-finite at the source, ` +\n          `(2) use $op($convert, { input: $.x, to: \"double\", onError: 0 }) to substitute a sentinel for any non-finite value, ` +\n          `(3) constrain to a known range (e.g. $.x > -1e300 && $.x < 1e300) if your domain allows it. See docs/DEFERRED.md.`,\n        pos,\n      );\n  }\n}\n\n// \u2500\u2500 Set method calls (ES2025) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * `new Set(a).intersection(new Set(b))` \u2192 `{ $setIntersection: [a, b] }`. The wrapper\n * is a JS-syntax tag for \"this is a set\"; codegen unwraps it on both receiver and\n * argument. MQL has no Set type \u2014 these compile to set operators on plain arrays.\n */\nfunction generateSetMethodCall(\n  receiver: { type: \"NewSet\"; arg: Expr | null; pos: number },\n  method: string,\n  args: CallArg[],\n  ctx: GenerateCtx,\n): unknown {\n  const pos = receiver.pos;\n  // `new Set(x?.y)` \u2014 if x is missing, treat the set as empty (JS semantics\n  // for `new Set(undefined)` is the empty set). Wrap the inner argument with\n  // $ifNull(v, []) when the chain is optional so `$setIntersection` and friends\n  // see an empty array instead of null.\n  const genSetInner = (inner: Expr): unknown => {\n    const gen = _generate(inner, ctx);\n    return chainHasOptional(inner) ? wrapIfNull(gen, []) : gen;\n  };\n  const lhs = receiver.arg ? genSetInner(receiver.arg) : [];\n  const exprArgs = exprArgsOnly(args, `Set.${method}`);\n  const requireSetArg = (): unknown => {\n    checkArity(method, { sig: \"other\", exact: 1 }, exprArgs.length, pos, \"Set.\");\n    const arg = exprArgs[0];\n    if (arg.type !== \"NewSet\") {\n      throw new CodegenError(\n        `Set.${method}()'s argument must be a 'new Set(...)' expression, not a plain value`,\n        arg.pos,\n      );\n    }\n    return arg.arg ? genSetInner(arg.arg) : [];\n  };\n  switch (method) {\n    case \"intersection\":\n      return { $setIntersection: [lhs, requireSetArg()] };\n    case \"union\":\n      return { $setUnion: [lhs, requireSetArg()] };\n    case \"difference\":\n      return { $setDifference: [lhs, requireSetArg()] };\n    case \"isSubsetOf\":\n      return { $setIsSubset: [lhs, requireSetArg()] };\n    case \"isSupersetOf\":\n      // A is a superset of B \u21D4 B is a subset of A\n      return { $setIsSubset: [requireSetArg(), lhs] };\n    case \"symmetricDifference\":\n    case \"isDisjointFrom\":\n      throw new CodegenError(\n        `Set.${method}() has no MongoDB equivalent \u2014 compose via $setDifference / $setIntersection / $setUnion as needed`,\n        pos,\n      );\n    default: {\n      const setHint = didYouMean(method, SET_METHODS);\n      throw new CodegenError(`Unknown Set method '.${method}()'.${setHint} Supported: ${SET_METHODS.join(\", \")}.`, pos);\n    }\n  }\n}\n\n// \u2500\u2500 Regex method calls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * `/pat/flags.test(str)` \u2192 `$regexMatch`; `/pat/flags.exec(str)` \u2192 `$regexFind`.\n * The regex literal supplies the pattern and flags; the str is the input.\n */\nfunction generateRegexMethodCall(\n  regex: { type: \"RegexLiteral\"; pattern: string; flags: string; pos: number },\n  method: string,\n  args: CallArg[],\n  ctx: GenerateCtx,\n): unknown {\n  const pos = regex.pos;\n  const exprArgs = exprArgsOnly(args, `regex.${method}`);\n  checkArity(method, { sig: \"str\", exact: 1 }, exprArgs.length, pos, \"regex.\");\n  const input = _generate(exprArgs[0], ctx);\n  const opName = method === \"test\" ? \"$regexMatch\" : method === \"exec\" ? \"$regexFind\" : null;\n  if (!opName) {\n    const regexHint = didYouMean(method, [\"test\", \"exec\"]);\n    throw new CodegenError(\n      `Unknown regex method '.${method}()'.${regexHint} Supported: regex.test(str), regex.exec(str).`,\n      pos,\n    );\n  }\n  const obj: Record<string, unknown> = { input, regex: regex.pattern };\n  if (regex.flags) obj[\"options\"] = regex.flags;\n  return { [opName]: obj };\n}\n\n// \u2500\u2500 UpdateOp codegen \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Compile a top-level `UpdateFilter` to either a single stage object (if\n * everything coalesces into one $set/$unset) or an array of stage objects.\n *\n * The shape mirrors `jsmql()`'s existing top-level convention: one stage \u2192\n * bare object, multiple stages \u2192 array.\n */\nexport function generateUpdateFilter(prog: UpdateFilter, ctx: GenerateCtx = EMPTY_CTX): object | object[] {\n  if (prog.ops.length === 0) {\n    throw new CodegenError(\"UpdateOp program must contain at least one assignment or delete\", prog.pos);\n  }\n  const groups = groupUpdateOps(prog.ops);\n  const stages = groups.map((g) => generateUpdateOpGroup(g, ctx));\n  if (stages.length === 1) return stages[0];\n  return stages;\n}\n\n/**\n * Coalescer used by both jsmql() top-level update ops and by pipeline.ts when\n * update ops appear as pipeline elements. Returns one or more stage objects.\n *\n * Grouping rule (preserves JS sequential semantics):\n *   - Consecutive same-kind (assign/delete) update ops join one group, UNLESS\n *   - A new update op's write path collides (equals or is a parent/child) with\n *     any prior write in the group, OR\n *   - For assignments: the new RHS reads any path that was written earlier in\n *     the group. (Delete has no reads.)\n */\nexport function generateUpdateOpGroups(ops: UpdateOp[], ctx: GenerateCtx = EMPTY_CTX): object[] {\n  const groups = groupUpdateOps(ops);\n  return groups.map((g) => generateUpdateOpGroup(g, ctx));\n}\n\nfunction groupUpdateOps(ops: UpdateOp[]): UpdateOp[][] {\n  const groups: UpdateOp[][] = [];\n  let current: UpdateOp[] = [];\n  let writes = new Set<string>();\n  let kind: \"assign\" | \"delete\" | null = null;\n\n  for (const m of ops) {\n    const myKind: \"assign\" | \"delete\" = m.type === \"AssignExpr\" ? \"assign\" : \"delete\";\n    const writePath = updateOpWritePath(m);\n    const reads = m.type === \"AssignExpr\" ? collectUpdateOpReads(m.value) : null;\n\n    let mustBreak = false;\n    if (kind !== null && kind !== myKind) {\n      mustBreak = true;\n    }\n    if (!mustBreak) {\n      for (const w of writes) {\n        if (pathsCollide(w, writePath)) {\n          mustBreak = true;\n          break;\n        }\n      }\n    }\n    if (!mustBreak && reads !== null) {\n      for (const r of reads) {\n        for (const w of writes) {\n          if (pathsCollide(w, r)) {\n            mustBreak = true;\n            break;\n          }\n        }\n        if (mustBreak) break;\n      }\n    }\n\n    if (mustBreak && current.length > 0) {\n      groups.push(current);\n      current = [];\n      writes = new Set();\n    }\n    current.push(m);\n    writes.add(writePath);\n    kind = myKind;\n  }\n  if (current.length > 0) groups.push(current);\n  return groups;\n}\n\nfunction generateUpdateOpGroup(group: UpdateOp[], ctx: GenerateCtx): object {\n  if (group.length === 0) {\n    internalError(\"empty update op group\");\n  }\n  if (group[0].type === \"AssignExpr\") {\n    const fields: Record<string, unknown> = {};\n    for (const m of group) {\n      if (m.type !== \"AssignExpr\") {\n        internalError(\"mixed-kind update op group\");\n      }\n      const path = updateOpWritePath(m);\n      if (Object.prototype.hasOwnProperty.call(fields, path)) {\n        internalError(`field '${path}' written twice in same group`);\n      }\n      fields[path] = _generate(m.value, ctx);\n    }\n    return { $set: fields };\n  }\n  // Delete group\n  const paths: string[] = [];\n  for (const m of group) {\n    if (m.type !== \"DeleteStmt\") {\n      internalError(\"mixed-kind update op group\");\n    }\n    paths.push(updateOpWritePath(m));\n  }\n  // MongoDB pipeline `$unset` accepts a single string OR an array of strings.\n  // Use the more compact string form for size 1 to match handwritten output.\n  return paths.length === 1 ? { $unset: paths[0] } : { $unset: paths };\n}\n\n/** Reconstruct the dotted write path from a update op target. */\nexport function updateOpWritePath(m: UpdateOp): string {\n  return targetToPath(m.target);\n}\n\nfunction targetToPath(target: Expr): string {\n  if (target.type === \"FieldRef\") return target.path;\n  if (target.type === \"MemberAccess\") {\n    return `${targetToPath(target.object)}.${target.member}`;\n  }\n  internalError(\"update op target is not a field path (parser should have rejected)\");\n}\n\n/**\n * Collect dotted field-path reads from an expression. Used by the coalescer\n * to detect read-after-write conflicts within a $set group. Lambda-local\n * params are intentionally not recorded \u2014 they reference iteration values,\n * not document fields.\n */\nfunction collectUpdateOpReads(expr: Expr): Set<string> {\n  const out = new Set<string>();\n  collectReadsInto(expr, out);\n  return out;\n}\n\nfunction collectReadsInto(expr: Expr, out: Set<string>): void {\n  // Foldable field path (`$.a`, `$.a.b.c`) \u2014 record as a single dotted entry.\n  const path = tryFieldPath(expr);\n  if (path !== null) {\n    out.add(path);\n    return;\n  }\n  switch (expr.type) {\n    case \"FieldRef\":\n      out.add(expr.path);\n      return;\n    case \"NumberLiteral\":\n    case \"BigIntLiteral\":\n    case \"StringLiteral\":\n    case \"BooleanLiteral\":\n    case \"NullLiteral\":\n    case \"UndefinedLiteral\":\n    case \"RegexLiteral\":\n    case \"ParamRef\":\n    case \"MathConst\":\n    case \"MathCallRef\":\n    case \"DateNow\":\n    case \"TypeCastRef\":\n      return;\n    case \"ArrayLiteral\":\n      for (const el of expr.elements) {\n        if (el.type === \"SpreadElement\") collectReadsInto(el.argument, out);\n        else if (el.type === \"AssignExpr\" || el.type === \"DeleteStmt\" || el.type === \"LetDecl\") {\n          // update ops/lets inside expressions are rejected elsewhere; ignore here\n        } else collectReadsInto(el, out);\n      }\n      return;\n    case \"ObjectLiteral\":\n      for (const e of expr.entries) {\n        if (e.type === \"SpreadElement\") {\n          collectReadsInto(e.argument, out);\n        } else {\n          if (e.key.kind === \"computed\") collectReadsInto(e.key.expr, out);\n          collectReadsInto(e.value, out);\n        }\n      }\n      return;\n    case \"TemplateLiteral\":\n      for (const e of expr.expressions) collectReadsInto(e, out);\n      return;\n    case \"BinaryExpr\":\n      collectReadsInto(expr.left, out);\n      collectReadsInto(expr.right, out);\n      return;\n    case \"UnaryExpr\":\n      collectReadsInto(expr.operand, out);\n      return;\n    case \"TernaryExpr\":\n      collectReadsInto(expr.condition, out);\n      collectReadsInto(expr.consequent, out);\n      collectReadsInto(expr.alternate, out);\n      return;\n    case \"IndexAccess\":\n      collectReadsInto(expr.object, out);\n      collectReadsInto(expr.index, out);\n      return;\n    case \"MemberAccess\":\n      collectReadsInto(expr.object, out);\n      return;\n    case \"MethodCall\":\n      collectReadsInto(expr.object, out);\n      collectArgsInto(expr.args, out);\n      return;\n    case \"CallExpression\":\n      collectReadsInto(expr.callee, out);\n      collectArgsInto(expr.args, out);\n      return;\n    case \"Lambda\":\n      // collectReadsInto runs on coalesced update-op RHS chains; block-form\n      // lambdas only appear inside `$$$.<coll>.find/filter(...)`, which is\n      // intercepted before this walker runs \u2014 so a block-form here is\n      // unreachable. Defensive guard: skip the body if absent.\n      if (expr.body !== undefined) collectReadsInto(expr.body, out);\n      return;\n    case \"TypeofExpr\":\n      collectReadsInto(expr.operand, out);\n      return;\n    case \"NewDate\":\n      for (const a of expr.args) collectReadsInto(a, out);\n      return;\n    case \"NewSet\":\n      if (expr.arg) collectReadsInto(expr.arg, out);\n      return;\n    case \"TypeCast\":\n      collectReadsInto(expr.arg, out);\n      return;\n    case \"MathCall\":\n    case \"ObjectCall\":\n      collectArgsInto(expr.args, out);\n      return;\n    case \"ArrayFrom\":\n      collectReadsInto(expr.input, out);\n      if (expr.mapFn) collectReadsInto(expr.mapFn, out);\n      return;\n    case \"NumberStatic\":\n      collectReadsInto(expr.arg, out);\n      return;\n    case \"OperatorCall\":\n      collectArgsInto(expr.args, out);\n      return;\n    case \"DateUTC\":\n      for (const a of expr.args) collectReadsInto(a, out);\n      return;\n  }\n}\n\nfunction collectArgsInto(args: CallArg[], out: Set<string>): void {\n  for (const a of args) {\n    if (a.type === \"SpreadElement\") collectReadsInto(a.argument, out);\n    else collectReadsInto(a, out);\n  }\n}\n\nfunction tryFieldPath(expr: Expr): string | null {\n  if (expr.type === \"FieldRef\") return expr.path;\n  if (expr.type === \"MemberAccess\") {\n    const base = tryFieldPath(expr.object);\n    if (base !== null) return `${base}.${expr.member}`;\n  }\n  return null;\n}\n\n/**\n * Two paths \"collide\" when one is the same as, or a strict ancestor of, the\n * other. `a` and `a` collide; `a` and `a.b` collide; `a` and `b` do not.\n * Used by the update op coalescer to detect conflicts that force a stage\n * boundary.\n */\nfunction pathsCollide(a: string, b: string): boolean {\n  if (a === b) return true;\n  if (a.length < b.length && b.startsWith(a) && b.charCodeAt(a.length) === 0x2e /* . */) {\n    return true;\n  }\n  if (b.length < a.length && a.startsWith(b) && a.charCodeAt(b.length) === 0x2e /* . */) {\n    return true;\n  }\n  return false;\n}\n", "// Aggregation pipeline stage registry.\n//\n// Stages live in stage position \u2014 the elements of a top-level pipeline array\n// like `[ { $match: ... }, { $sort: ... } ]`. They are distinct from\n// expression operators (src/operators.ts), which live in value position\n// inside a stage spec. Both registries follow the same single-source-of-truth\n// rule: do not hand-write `if (name === \"$match\")` in the parser or codegen\n// or pipeline lowering \u2014 register the stage here and read it back.\n//\n// Descriptions are lifted from vendor/mql-specifications/definitions/stage/<name>.yaml\n// at the pinned commit (see vendor/fetch-mql-specs.mjs).\n\nexport type StageDef = {\n  description: string;\n  /**\n   * Body keys whose value is itself a sub-pipeline (an array of stage\n   * objects). The sentinel `\"*\"` means every value of the body object is a\n   * sub-pipeline (used for `$facet`).\n   */\n  subPipelineFields: readonly string[];\n  /**\n   * Set on the *diagnostic / system* source stages (`$indexStats`,\n   * `$currentOp`, \u2026). These don't transform an incoming stream \u2014 they produce\n   * one \u2014 so they must be the pipeline's first stage, and they differ by\n   * *where* they legally run. jsmql surfaces a scope-encoding sugar\n   * (`$$.indexStats()` collection, `$$$$.currentOp()` / `$$$$.shardedDataDistribution()`\n   * cluster/server) driven entirely off this field; see\n   * src/system-stage-translation.ts. Two tiers are in use \u2014 collection (`$$`)\n   * and cluster/server (`$$$$`); the `currentOp` family runs on the admin\n   * database, not the current one, so it's cluster-scoped, not `database`.\n   * `options: false` marks the stages that take no options object\n   * (`{ $indexStats: {} }`).\n   */\n  diagnostic?: { scope: \"collection\" | \"database\" | \"cluster\"; options: boolean };\n  /**\n   * Absolute positional constraint, knowable purely from pipeline shape:\n   *   \"first\" \u2014 must sit at index 0 of whatever pipeline it appears in. Set on\n   *             *source* stages that produce (not transform) documents and so\n   *             ignore any incoming stream. The 9 `diagnostic` stages are also\n   *             must-be-first \u2014 `stageMustBeFirst` derives that from\n   *             `diagnostic`, so they do NOT repeat `position` here.\n   *   \"last\"  \u2014 must be the final stage (a write / terminal stage).\n   * Enforced for the literal stage forms (`{ $merge: \u2026 }`) by pipeline.ts; the\n   * sugar forms (`$out` / `$$.indexStats()` / \u2026) keep their own dedicated,\n   * sugar-aware messages. See docs/specs/pipeline-validation.md.\n   */\n  position?: \"first\" | \"last\";\n  /**\n   * Sub-pipeline containers this stage may not appear inside. The container\n   * kind is the stage that owns the sub-pipeline: \"facet\" (`$facet.*`),\n   * \"lookup\" (`$lookup.pipeline`), \"unionWith\" (`$unionWith.pipeline`).\n   * `$out`/`$merge` are forbidden in all three; the `$facet` forbidden-stage\n   * list (per the MongoDB `$facet` reference) bans source/search/write stages\n   * inside a facet sub-pipeline.\n   */\n  forbiddenIn?: readonly (\"facet\" | \"lookup\" | \"unionWith\")[];\n};\n\nexport const STAGES: Record<string, StageDef> = {\n  $addFields: {\n    description:\n      \"Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields.\",\n    subPipelineFields: [],\n  },\n  $bucket: {\n    description:\n      \"Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries.\",\n    subPipelineFields: [],\n  },\n  $bucketAuto: {\n    description:\n      \"Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets.\",\n    subPipelineFields: [],\n  },\n  $changeStream: {\n    description:\n      \"Returns a Change Stream cursor for the collection or database. This stage can only occur once in an aggregation pipeline and it must occur as the first stage.\",\n    subPipelineFields: [],\n    position: \"first\",\n  },\n  $changeStreamSplitLargeEvent: {\n    description:\n      \"Splits large change stream events that exceed 16 MB into smaller fragments returned in a change stream cursor.\",\n    subPipelineFields: [],\n    position: \"last\",\n  },\n  $collStats: {\n    description: \"Returns statistics regarding a collection or view.\",\n    subPipelineFields: [],\n    diagnostic: { scope: \"collection\", options: true },\n    forbiddenIn: [\"facet\"],\n  },\n  $count: {\n    description: \"Returns a count of the number of documents at this stage of the aggregation pipeline.\",\n    subPipelineFields: [],\n  },\n  $currentOp: {\n    description: \"Returns information on active and/or dormant operations for the MongoDB deployment.\",\n    subPipelineFields: [],\n    // Server/deployment-level: must be run on the admin database\n    // (`db.getSiblingDB(\"admin\").aggregate(...)`), not the current database.\n    diagnostic: { scope: \"cluster\", options: true },\n  },\n  $densify: {\n    description: \"Creates new documents in a sequence of documents where certain values in a field are missing.\",\n    subPipelineFields: [],\n  },\n  $documents: { description: \"Returns literal documents from input values.\", subPipelineFields: [], position: \"first\" },\n  $facet: {\n    description:\n      \"Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables multi-faceted aggregations characterizing data across multiple dimensions in a single stage.\",\n    // Every value in the body object is itself a sub-pipeline.\n    subPipelineFields: [\"*\"],\n    // $facet cannot be nested inside another $facet.\n    forbiddenIn: [\"facet\"],\n  },\n  $fill: { description: \"Populates null and missing field values within documents.\", subPipelineFields: [] },\n  $geoNear: {\n    description:\n      \"Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data.\",\n    subPipelineFields: [],\n    position: \"first\",\n    // Allowed as the first stage of a $lookup/$unionWith sub-pipeline, so only facet is banned.\n    forbiddenIn: [\"facet\"],\n  },\n  $graphLookup: {\n    description:\n      \"Performs a recursive search on a collection. Adds a new array field to each output document that contains the traversal results of the recursive search.\",\n    subPipelineFields: [],\n  },\n  $group: {\n    description:\n      \"Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group.\",\n    subPipelineFields: [],\n  },\n  $indexStats: {\n    description: \"Returns statistics regarding the use of each index for the collection.\",\n    subPipelineFields: [],\n    diagnostic: { scope: \"collection\", options: false },\n    forbiddenIn: [\"facet\"],\n  },\n  $limit: {\n    description: \"Passes the first n documents unmodified to the pipeline where n is the specified limit.\",\n    subPipelineFields: [],\n  },\n  $listLocalSessions: {\n    description: \"Lists all active sessions recently in use on the currently connected mongos or mongod instance.\",\n    subPipelineFields: [],\n    // Server-level: run on the admin database (`db.aggregate(...)`).\n    diagnostic: { scope: \"cluster\", options: true },\n  },\n  $listSampledQueries: {\n    description: \"Lists sampled queries for all collections or a specific collection.\",\n    subPipelineFields: [],\n    // Cluster-level: run on the admin database.\n    diagnostic: { scope: \"cluster\", options: true },\n  },\n  $listSearchIndexes: {\n    description: \"Returns information about existing Atlas Search indexes on a specified collection.\",\n    subPipelineFields: [],\n    diagnostic: { scope: \"collection\", options: true },\n  },\n  $listSessions: {\n    description: \"Lists all sessions that have been active long enough to propagate to the system.sessions collection.\",\n    subPipelineFields: [],\n    // Cluster-level: reads the cluster-wide config.system.sessions collection.\n    diagnostic: { scope: \"cluster\", options: true },\n  },\n  $lookup: {\n    description:\n      \"Performs a left outer join to another collection in the same database to filter in documents from the joined collection for processing.\",\n    subPipelineFields: [\"pipeline\"],\n  },\n  $match: {\n    description:\n      \"Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage.\",\n    subPipelineFields: [],\n  },\n  $merge: {\n    description:\n      \"Writes the resulting documents of the aggregation pipeline to a collection. Must be the last stage in the pipeline.\",\n    subPipelineFields: [],\n    position: \"last\",\n    forbiddenIn: [\"facet\", \"lookup\", \"unionWith\"],\n  },\n  $out: {\n    description:\n      \"Writes the resulting documents of the aggregation pipeline to a collection. Must be the last stage in the pipeline.\",\n    subPipelineFields: [],\n    position: \"last\",\n    forbiddenIn: [\"facet\", \"lookup\", \"unionWith\"],\n  },\n  $planCacheStats: {\n    description: \"Returns plan cache information for a collection.\",\n    subPipelineFields: [],\n    diagnostic: { scope: \"collection\", options: false },\n    forbiddenIn: [\"facet\"],\n  },\n  $project: {\n    description:\n      \"Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document.\",\n    subPipelineFields: [],\n  },\n  $rankFusion: {\n    description: \"Combines multiple pipelines using rank-based fusion to create hybrid search results.\",\n    subPipelineFields: [],\n  },\n  $redact: {\n    description:\n      \"Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves.\",\n    subPipelineFields: [],\n  },\n  $replaceRoot: {\n    description:\n      \"Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field.\",\n    subPipelineFields: [],\n  },\n  $replaceWith: {\n    description:\n      \"Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field.\",\n    subPipelineFields: [],\n  },\n  $sample: { description: \"Randomly selects the specified number of documents from its input.\", subPipelineFields: [] },\n  $scoreFusion: {\n    description: \"Combines multiple pipelines using relative score fusion to create hybrid search results.\",\n    subPipelineFields: [],\n  },\n  $search: {\n    description: \"Performs a full-text search of the field or fields in an Atlas collection.\",\n    subPipelineFields: [],\n    position: \"first\",\n    // Allowed as the first stage of a $lookup/$unionWith sub-pipeline, so only facet is banned.\n    forbiddenIn: [\"facet\"],\n  },\n  $searchMeta: {\n    description:\n      \"Returns different types of metadata result documents for the Atlas Search query against an Atlas collection.\",\n    subPipelineFields: [],\n    position: \"first\",\n    forbiddenIn: [\"facet\"],\n  },\n  $set: {\n    description:\n      \"Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields.\",\n    subPipelineFields: [],\n  },\n  $setWindowFields: {\n    description: \"Groups documents into windows and applies one or more operators to the documents in each window.\",\n    subPipelineFields: [],\n  },\n  $shardedDataDistribution: {\n    description: \"Provides data and size distribution information on sharded collections.\",\n    subPipelineFields: [],\n    diagnostic: { scope: \"cluster\", options: false },\n  },\n  $skip: {\n    description:\n      \"Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline.\",\n    subPipelineFields: [],\n  },\n  $sort: {\n    description:\n      \"Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified.\",\n    subPipelineFields: [],\n  },\n  $sortByCount: {\n    description:\n      \"Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group.\",\n    subPipelineFields: [],\n  },\n  $unionWith: {\n    description:\n      \"Performs a union of two collections; combines pipeline results from two collections into a single result set.\",\n    subPipelineFields: [\"pipeline\"],\n  },\n  $unset: { description: \"Removes or excludes fields from documents.\", subPipelineFields: [] },\n  $unwind: {\n    description:\n      \"Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value.\",\n    subPipelineFields: [],\n  },\n  $vectorSearch: {\n    description: \"Performs an ANN or ENN search on a vector in the specified field.\",\n    subPipelineFields: [],\n    position: \"first\",\n    forbiddenIn: [\"facet\"],\n  },\n};\n\nexport function lookupStage(name: string): StageDef | undefined {\n  return Object.prototype.hasOwnProperty.call(STAGES, name) ? STAGES[name] : undefined;\n}\n\n/**\n * Must this stage sit at index 0 of its pipeline? True for the explicit\n * `position: \"first\"` source stages AND for every diagnostic stage \u2014 a\n * diagnostic produces its own document stream (index/collection stats, running\n * ops, \u2026) and ignores any input, so a non-first placement has no valid runtime\n * context. Deriving the diagnostics here keeps the literal-form check in step\n * with the sugar-form check (system-stage-translation.ts) off one source.\n */\nexport function stageMustBeFirst(def: StageDef): boolean {\n  return def.position === \"first\" || def.diagnostic !== undefined;\n}\n\n/** Must this stage be the final stage of its pipeline (a write / terminal stage)? */\nexport function stageMustBeLast(def: StageDef): boolean {\n  return def.position === \"last\";\n}\n\n/** Is this stage forbidden inside the given sub-pipeline container kind? */\nexport function stageForbiddenIn(def: StageDef, container: \"facet\" | \"lookup\" | \"unionWith\"): boolean {\n  return def.forbiddenIn?.includes(container) ?? false;\n}\n", "// $match expression-body \u2192 query-language translator.\n//\n// Translates the subset of expression bodies that MongoDB's query language\n// can represent directly, so $match emits an index-friendly shape instead of\n// always wrapping in $expr (which disables index usage). Untranslatable parts\n// of the expression are returned as a `residual` that the caller wraps in\n// $expr \u2014 yielding `{ $match: { <translated>, $expr: <residual> } }`, which\n// keeps the planner using indexes on the translatable half.\n//\n// Known semantic divergences between query-language and aggregation $eq are\n// documented in `docs/specs/match-query-translation.md`. Users who need\n// strict aggregation semantics opt out via the existing object-literal\n// passthrough: `$match({ $expr: <expr> })`.\n//\n// This module is pure \u2014 no MQL knowledge beyond what's encoded here, no\n// reach-into-codegen for leaves. Residual sub-expressions get handed back\n// as Expr nodes; the caller re-enters `generate()` on them.\n\nimport type { Expr, BinaryOp } from \"./ast.ts\";\nimport { isOpaqueBsonValue, generateWithCtx, mqlForBinaryOp } from \"./codegen.ts\";\nimport type { GenerateCtx } from \"./codegen.ts\";\n\nexport type MatchTranslation = {\n  /** The translated query-language fragment. Empty when nothing translated. */\n  query: Record<string, unknown>;\n  /** Remaining expression that couldn't be translated. Null when fully translated. */\n  residual: Expr | null;\n};\n\n/**\n * Merge a `MatchTranslation` into a single query document: the index-friendly\n * `query` conjuncts plus, when present, the untranslatable `residual` lowered\n * through codegen and wrapped in `$expr`. Returns `null` for a vacuous predicate\n * (empty query, no residual) so callers can skip emitting a `$match` entirely.\n *\n * This is the one place the four-way query / `$expr` emission lives \u2014 vacuous \u2192\n * `null`; pure query \u2192 `query`; pure residual \u2192 `{ $expr }`; both \u2192 merged. Every\n * consumer of `translateMatchBody` (the top-level Filter in index.ts, the\n * `$match` stage body in pipeline.ts, and `matchStagesFromTranslation` for the\n * sub-pipeline translators) routes through it so the emitted shape can't drift.\n */\nexport function mergeTranslatedQuery(t: MatchTranslation, ctx: GenerateCtx): Record<string, unknown> | null {\n  const queryEmpty = Object.keys(t.query).length === 0;\n  if (t.residual === null) return queryEmpty ? null : t.query;\n  const exprBody = generateWithCtx(t.residual, ctx);\n  if (queryEmpty) return { $expr: exprBody };\n  return { ...t.query, $expr: exprBody };\n}\n\n/**\n * Optional context passed in by the pipeline lowerer. `bindings` lets the\n * translator treat function-form parameter references as literals \u2014 the\n * `ParamRef` node still says \"param x\", but its value at this codegen call\n * is a compile-time constant from `jsmql.compile(fn)(params)`. Without this\n * hook the index-friendly path can't see across the binding and would emit\n * `$expr` for every comparison that touches a parameter.\n */\nexport type TranslateCtx = { bindings?: ReadonlyMap<string, unknown> };\n\nexport function translateMatchBody(body: Expr, ctx: TranslateCtx = {}): MatchTranslation {\n  return translate(body, ctx);\n}\n\nfunction translate(expr: Expr, ctx: TranslateCtx): MatchTranslation {\n  if (expr.type === \"BinaryExpr\" && expr.op === \"&&\") {\n    // Pre-pass: when the entire &&-chain is `field.includes(<lit>)` calls on\n    // the same field, fold to `{ field: { $all: [<lits>] } }`. Strictly a\n    // compactness optimisation \u2014 `$and: [{ f: a }, { f: b }]` matches the\n    // same array-valued docs as `$all: [a, b]` \u2014 so it doesn't change\n    // semantics; just emits the shorter MQL the user almost certainly meant.\n    // Mixed chains (one .includes plus other predicates) fall through to the\n    // normal combineAnd path; the user can rearrange to enable the fold.\n    const allFold = extractIncludesChain(expr);\n    if (allFold !== null) {\n      return { query: { [allFold.field]: { $all: allFold.values } }, residual: null };\n    }\n    return combineAnd(translate(expr.left, ctx), translate(expr.right, ctx));\n  }\n  if (expr.type === \"BinaryExpr\" && expr.op === \"||\") {\n    return combineOr(translate(expr.left, ctx), translate(expr.right, ctx), expr);\n  }\n  const leaf = translateLeaf(expr, ctx);\n  if (leaf === null) return { query: {}, residual: expr };\n  return { query: leaf, residual: null };\n}\n\nfunction combineAnd(left: MatchTranslation, right: MatchTranslation): MatchTranslation {\n  return { query: mergeQuery(left.query, right.query), residual: combineResidualsAnd(left.residual, right.residual) };\n}\n\nfunction combineOr(left: MatchTranslation, right: MatchTranslation, original: Expr): MatchTranslation {\n  // $or can't carry a residual \u2014 mixing index-using $or branches with a\n  // disjoint $expr would lose the disjunction guarantee. If either branch\n  // has anything residual or empty, the whole `||` becomes residual.\n  if (left.residual !== null || right.residual !== null) {\n    return { query: {}, residual: original };\n  }\n  if (isEmpty(left.query) || isEmpty(right.query)) {\n    return { query: {}, residual: original };\n  }\n  return { query: { $or: [left.query, right.query] }, residual: null };\n}\n\n/**\n * Merge two query-document fragments so that **only colliding field names**\n * are pushed into `$and` \u2014 non-colliding fields stay at the top level where\n * MongoDB's planner can use indexes on them directly.\n *\n * Worked example: `$.customerId === \"cust_42\" && $.placedAt >= \"2026-01-01\"\n * && $.placedAt < \"2026-02-01\" && $.status === \"shipped\"` should produce\n *\n *     {\n *       customerId: \"cust_42\",\n *       $and: [\n *         { placedAt: { $gte: \"2026-01-01\" } },\n *         { placedAt: { $lt: \"2026-02-01\" } },\n *       ],\n *       status: \"shipped\",\n *     }\n *\n * \u2014 `customerId` and `status` stay top-level (one occurrence each), the two\n * `placedAt` predicates fold into `$and`. Without this, the planner can't\n * use indexes on the non-colliding fields when they're trapped inside `$and`\n * alongside the collision pair.\n *\n * Algorithm: flatten both inputs into an ordered list of `(key, value)`\n * clauses (expanding any pre-existing `$and` element into its constituent\n * single-key clauses); count occurrences per key; emit a clause at the top\n * level when its key occurs once, or push it into a freshly-created `$and`\n * when its key collides. `$and` is inserted at the position of the FIRST\n * colliding key so the output's key order follows the source order.\n */\nfunction mergeQuery(a: Record<string, unknown>, b: Record<string, unknown>): Record<string, unknown> {\n  if (isEmpty(a)) return b;\n  if (isEmpty(b)) return a;\n\n  type Clause = { key: string; value: unknown };\n  const clauses: Clause[] = [];\n  const collect = (doc: Record<string, unknown>) => {\n    for (const k of Object.keys(doc)) {\n      if (k === \"$and\" && Array.isArray(doc[k])) {\n        for (const inner of doc[k] as Record<string, unknown>[]) {\n          for (const ik of Object.keys(inner)) {\n            clauses.push({ key: ik, value: inner[ik] });\n          }\n        }\n      } else {\n        clauses.push({ key: k, value: doc[k] });\n      }\n    }\n  };\n  collect(a);\n  collect(b);\n\n  const counts = new Map<string, number>();\n  for (const c of clauses) counts.set(c.key, (counts.get(c.key) ?? 0) + 1);\n\n  const out: Record<string, unknown> = {};\n  let andClauses: Record<string, unknown>[] | null = null;\n  for (const c of clauses) {\n    if ((counts.get(c.key) ?? 0) > 1) {\n      if (andClauses === null) {\n        andClauses = [];\n        // Inserting `$and` at this position pins it between the surrounding\n        // single-key clauses in source order, so the output reads top-to-\n        // bottom the way the user wrote the original `&&` chain.\n        out.$and = andClauses;\n      }\n      andClauses.push({ [c.key]: c.value });\n    } else {\n      out[c.key] = c.value;\n    }\n  }\n  return out;\n}\n\nfunction isEmpty(q: Record<string, unknown>): boolean {\n  return Object.keys(q).length === 0;\n}\n\nfunction combineResidualsAnd(a: Expr | null, b: Expr | null): Expr | null {\n  if (a === null) return b;\n  if (b === null) return a;\n  return { type: \"BinaryExpr\", op: \"&&\", left: a, right: b, pos: a.pos };\n}\n\nfunction translateLeaf(expr: Expr, ctx: TranslateCtx): Record<string, unknown> | null {\n  // Bare boolean method calls \u2014 `.includes(x)`, `.match(/re/)`, `.some(p)` \u2014\n  // can be the entire predicate body (no `=== true` wrapper), so they're\n  // tried before the BinaryExpr machinery.\n  if (expr.type === \"MethodCall\") {\n    const m = translateBooleanMethodCall(expr, ctx);\n    if (m !== null) return m;\n  }\n  if (expr.type !== \"BinaryExpr\") return null;\n  const op = expr.op;\n  if (isEqualityOp(op)) {\n    // Each peephole is tried before the generic equality path so the field-\n    // path-and-literal orientation logic doesn't see the wrapping construct\n    // (typeof, member access for `.length`, BinaryExpr `%`, \u2026).\n    if (op === \"===\" || op === \"!==\") {\n      const typed = translateTypeofPredicate(expr.left, expr.right, op);\n      if (typed !== null) return typed;\n      const undef = translateUndefinedPredicate(expr.left, expr.right, op);\n      if (undef !== null) return undef;\n      // `.length` (or the JS-identical `[\"length\"]`) compared against a natural\n      // number is the *length* of a string-or-array, not a field named\n      // `length`. Residualise into `$expr` so codegen emits the runtime\n      // `$isArray`/`$size`/`$strLenCP` dispatch (which, unlike `$size`, also\n      // handles strings). Comparisons against a non-natural value fall through\n      // to the generic path, which treats `.length` as a literal field path.\n      if (isLengthVsNatural(expr.left, expr.right)) return null;\n      const md = translateModulo(expr.left, expr.right, op);\n      if (md !== null) return md;\n    }\n    return translateEquality(expr.left, expr.right, op, ctx);\n  }\n  if (isOrderedOp(op)) {\n    if (isLengthVsNatural(expr.left, expr.right)) return null;\n    return translateOrderedCompare(expr.left, expr.right, op, ctx);\n  }\n  return null;\n}\n\n/**\n * Bare boolean method calls in `$match` body \u2014 `.includes(lit)`, `.match(/re/)`,\n * `.some(p)`. Each produces an index-friendly query-doc shape when the receiver\n * and the argument are compatible; otherwise returns null and the body falls\n * through to `$expr`.\n */\nfunction translateBooleanMethodCall(\n  expr: Expr & { type: \"MethodCall\" },\n  ctx: TranslateCtx,\n): Record<string, unknown> | null {\n  if (expr.method === \"includes\") return translateIncludesCall(expr, ctx);\n  if (expr.method === \"match\") return translateMatchCall(expr);\n  if (expr.method === \"some\") return translateSomeCall(expr, ctx);\n  return null;\n}\n\n/**\n * `.includes()` \u2014 two query-position forms:\n *   - `$.tags.includes(\"vip\")` \u2192 `{ tags: \"vip\" }` (implicit array-element /\n *     scalar-equality match \u2014 MongoDB's \"value or array-containing-value\"\n *     semantics line up with JS-on-arrays exactly).\n *   - `[\"a\",\"b\"].includes($.status)` \u2192 `{ status: { $in: [\"a\",\"b\"] } }`\n *     (set membership).\n *\n * Form 1 diverges from jsmql's expression-position `.includes()` translation\n * (which handles both array and string substring via `$cond` + `$indexOfCP`):\n * here we only emit the array-element form. For string-substring queries,\n * users reach for `.match(/.../)` (or the explicit `$op($indexOfCP, \u2026)`).\n * Documented in `docs/specs/match-query-translation.md`.\n */\nfunction translateIncludesCall(expr: Expr & { type: \"MethodCall\" }, ctx: TranslateCtx): Record<string, unknown> | null {\n  if (expr.args.length !== 1) return null;\n  const arg = expr.args[0];\n  if (arg.type === \"SpreadElement\") return null;\n  // Form 1: field.includes(<literal>)\n  const recvField = asFieldPath(expr.object);\n  if (recvField !== null) {\n    const lit = anyEqualityLiteral(arg, ctx);\n    if (lit !== null) return { [recvField]: lit.value };\n  }\n  // Form 2: <array-literal-of-literals>.includes(<field>)\n  if (expr.object.type === \"ArrayLiteral\") {\n    const argField = asFieldPath(arg);\n    if (argField === null) return null;\n    const values: unknown[] = [];\n    for (const el of expr.object.elements) {\n      // ArrayElement is wider than Expr \u2014 it allows update-op shapes inside\n      // pipeline arrays. None of those are valid in an `.includes()`-arg\n      // literal, so we reject and fall through to the expression-form\n      // translation, which produces the precise error if needed.\n      if (el.type === \"SpreadElement\") return null;\n      if (el.type === \"AssignExpr\" || el.type === \"DeleteStmt\" || el.type === \"LetDecl\") return null;\n      const lit = anyEqualityLiteral(el, ctx);\n      if (lit === null) return null;\n      values.push(lit.value);\n    }\n    return { [argField]: { $in: values } };\n  }\n  return null;\n}\n\n/**\n * Walk a `&&`-tree and, if **every** leaf is `field.includes(<lit>)` on the\n * **same** field, return `{ field, values: [...lits] }`. Returns null on any\n * deviation \u2014 a different op, a different field, a non-literal arg, anything.\n *\n * Used by `translate()` to fold the chain into `$all` before the generic\n * `combineAnd` path sees it. Mixed chains (some leaves are `.includes`, others\n * aren't) deliberately fall through; the user can reorder if they want the\n * fold, and the un-folded `$and` of identical-shape clauses is identical\n * in semantics anyway.\n */\nfunction extractIncludesChain(expr: Expr): { field: string; values: unknown[] } | null {\n  if (expr.type === \"BinaryExpr\" && expr.op === \"&&\") {\n    const left = extractIncludesChain(expr.left);\n    if (left === null) return null;\n    const right = extractIncludesChain(expr.right);\n    if (right === null) return null;\n    if (left.field !== right.field) return null;\n    return { field: left.field, values: [...left.values, ...right.values] };\n  }\n  if (expr.type !== \"MethodCall\" || expr.method !== \"includes\") return null;\n  if (expr.args.length !== 1) return null;\n  const field = asFieldPath(expr.object);\n  if (field === null) return null;\n  const arg = expr.args[0];\n  if (arg.type === \"SpreadElement\") return null;\n  const lit = anyEqualityLiteral(arg, /*ctx*/ {});\n  if (lit === null) return null;\n  return { field, values: [lit.value] };\n}\n\n/**\n * `$.name.match(/^a/i)` \u2192 `{ name: /^a/i }`. Only the field-receiver,\n * regex-literal-arg form translates; anything else (string arg, computed\n * regex, non-field receiver) falls through to `$expr` where the existing\n * `$regexMatch` translation handles it.\n */\nfunction translateMatchCall(expr: Expr & { type: \"MethodCall\" }): Record<string, unknown> | null {\n  if (expr.args.length !== 1) return null;\n  const field = asFieldPath(expr.object);\n  if (field === null) return null;\n  const arg = expr.args[0];\n  if (arg.type !== \"RegexLiteral\") return null;\n  // Reconstruct the regex literal as a real JS RegExp so the driver\n  // serialises it as BSON regex (rather than a plain object).\n  const re = new RegExp(arg.pattern, arg.flags);\n  return { [field]: re };\n}\n\n/**\n * `$.items.some(item => <predicate>)` \u2192 `{ items: { $elemMatch: <translated-body> } }`\n * \u2014 but only when the lambda body itself translates entirely (no residual).\n * If the body has anything index-unfriendly, the whole `.some` falls through\n * to the expression-form `$anyElementTrue` path so we don't mix index-friendly\n * and `$expr` semantics inside one `$elemMatch`.\n */\nfunction translateSomeCall(expr: Expr & { type: \"MethodCall\" }, ctx: TranslateCtx): Record<string, unknown> | null {\n  if (expr.args.length !== 1) return null;\n  const field = asFieldPath(expr.object);\n  if (field === null) return null;\n  const lam = expr.args[0];\n  if (lam.type !== \"Lambda\" || lam.params.length !== 1) return null;\n  if (lam.body === undefined) return null;\n  const param = lam.params[0];\n  // Rewrite `<param>.x` \u2192 `$.x` in the body so the inner translator (which\n  // treats `$.` as the doc-relative field path) gets a recognisable shape.\n  // `$elemMatch`'s query document is matched against each array element as if\n  // *it* were the root doc, so the rewrite is faithful.\n  const rewritten = rewriteParamAsRoot(lam.body, param);\n  if (rewritten === null) return null;\n  const inner = translate(rewritten, ctx);\n  if (inner.residual !== null) return null;\n  if (isEmpty(inner.query)) return null;\n  return { [field]: { $elemMatch: inner.query } };\n}\n\n/**\n * Inside `.some(item => \u2026)` the lambda parameter (`item`) plays the role of\n * the current element. `$elemMatch` evaluates its query doc against the\n * element as if it were the root, so `item.qty` should translate the same\n * way `$.qty` would. This rewriter walks the body, swapping every\n * `MemberAccess { object: ParamRef(<param>) }` chain into the equivalent\n * `FieldRef` / dotted-`FieldRef` shape; bare `ParamRef(<param>)` (no access)\n * isn't representable as a field path, so we bail.\n */\nfunction rewriteParamAsRoot(expr: Expr, param: string): Expr | null {\n  if (expr.type === \"ParamRef\" && expr.name === param) return null;\n  if (expr.type === \"MemberAccess\") {\n    const innerField = paramMemberAsField(expr, param);\n    if (innerField !== null) return { type: \"FieldRef\", path: innerField, pos: expr.pos };\n    const newObj = rewriteParamAsRoot(expr.object, param);\n    if (newObj === null) return null;\n    return { ...expr, object: newObj };\n  }\n  if (expr.type === \"BinaryExpr\") {\n    const left = rewriteParamAsRoot(expr.left, param);\n    if (left === null) return null;\n    const right = rewriteParamAsRoot(expr.right, param);\n    if (right === null) return null;\n    return { ...expr, left, right };\n  }\n  if (expr.type === \"UnaryExpr\") {\n    const operand = rewriteParamAsRoot(expr.operand, param);\n    if (operand === null) return null;\n    return { ...expr, operand };\n  }\n  if (expr.type === \"MethodCall\") {\n    const obj = rewriteParamAsRoot(expr.object, param);\n    if (obj === null) return null;\n    return { ...expr, object: obj };\n  }\n  if (expr.type === \"TypeofExpr\") {\n    const operand = rewriteParamAsRoot(expr.operand, param);\n    if (operand === null) return null;\n    return { ...expr, operand };\n  }\n  // Literals and unrelated FieldRefs pass through unchanged.\n  return expr;\n}\n\nfunction paramMemberAsField(expr: Expr & { type: \"MemberAccess\" }, param: string): string | null {\n  if (expr.object.type === \"ParamRef\" && expr.object.name === param) return expr.member;\n  if (expr.object.type === \"MemberAccess\") {\n    const base = paramMemberAsField(expr.object, param);\n    if (base !== null) return `${base}.${expr.member}`;\n  }\n  return null;\n}\n\n/**\n * `$.field === undefined` \u2192 `{ field: { $exists: false } }`;\n * `$.field !== undefined` \u2192 `{ field: { $exists: true } }`. Mirrors JS's\n * \"value is undefined / missing\" semantics \u2014 both branches of MongoDB's\n * `$exists` line up. (Distinct from `=== null`, which lowers to\n * `$type: \"null\"` \u2014 present-and-null only.)\n */\nfunction translateUndefinedPredicate(left: Expr, right: Expr, op: \"===\" | \"!==\"): Record<string, unknown> | null {\n  const undefSide = left.type === \"UndefinedLiteral\" ? right : right.type === \"UndefinedLiteral\" ? left : null;\n  if (undefSide === null) return null;\n  const field = asFieldPath(undefSide);\n  if (field === null) return null;\n  if (op === \"===\") return { [field]: { $exists: false } };\n  return { [field]: { $exists: true } };\n}\n\n/**\n * A `.length` member access. Only the dot form is interpreted as a length \u2014\n * bracket access (`[\"length\"]`) is raw data access and is never folded here.\n */\nfunction isLengthAccess(expr: Expr): boolean {\n  return expr.type === \"MemberAccess\" && expr.member === \"length\";\n}\n\n/**\n * `<length-access> <cmp> <natural-number-literal>` (either orientation). A\n * length compared against a natural number (`isIntegerLiteral` = non-negative\n * integer) is unambiguously a length; when true the comparison residualises to\n * `$expr` for the string-or-array `$cond`. Against any other RHS (`3.5`,\n * negative, a string, a non-literal) `.length` is read as a literal field path\n * instead \u2014 a length can't sensibly equal a non-natural value.\n */\nfunction isLengthVsNatural(left: Expr, right: Expr): boolean {\n  return (isLengthAccess(left) && isIntegerLiteral(right)) || (isLengthAccess(right) && isIntegerLiteral(left));\n}\n\nfunction isIntegerLiteral(expr: Expr): boolean {\n  return expr.type === \"NumberLiteral\" && Number.isInteger(expr.value) && expr.value >= 0;\n}\n\n/**\n * Emit `{ [field]: positive }` for a `===` predicate, or `{ [field]: { $not:\n * positive } }` for `!==`. The shared shape for any equality-family peephole\n * whose negation is a `$not` wrap of an inner query operator (`$mod`, `$type`,\n * \u2026) \u2014 each such translator supplies only the positive operator object and gets\n * the `!==` form for free. (Equality-shorthand and `$exists` negate differently\n * \u2014 `$ne` and a flipped boolean \u2014 so they don't use this.)\n */\nfunction fieldQueryOrNegated(\n  field: string,\n  positive: Record<string, unknown>,\n  op: \"===\" | \"!==\",\n): Record<string, unknown> {\n  return { [field]: op === \"===\" ? positive : { $not: positive } };\n}\n\n/**\n * `$.x % N === M` \u2192 `{ x: { $mod: [N, M] } }`. Both `N` (divisor) and `M`\n * (remainder) must be integer literals; the field path must be a clean\n * `$.<path>` (no method calls, no further arithmetic).\n */\nfunction translateModulo(left: Expr, right: Expr, op: \"===\" | \"!==\"): Record<string, unknown> | null {\n  const oriented = orientModuloAndInt(left, right);\n  if (oriented === null) return null;\n  return fieldQueryOrNegated(oriented.field, { $mod: [oriented.divisor, oriented.remainder] }, op);\n}\n\nfunction orientModuloAndInt(left: Expr, right: Expr): { field: string; divisor: number; remainder: number } | null {\n  const lm = asModuloFieldAndDivisor(left);\n  if (lm !== null && isIntegerLiteral(right)) {\n    return {\n      field: lm.field,\n      divisor: lm.divisor,\n      remainder: (right as { type: \"NumberLiteral\"; value: number }).value,\n    };\n  }\n  const rm = asModuloFieldAndDivisor(right);\n  if (rm !== null && isIntegerLiteral(left)) {\n    return {\n      field: rm.field,\n      divisor: rm.divisor,\n      remainder: (left as { type: \"NumberLiteral\"; value: number }).value,\n    };\n  }\n  return null;\n}\n\nfunction asModuloFieldAndDivisor(expr: Expr): { field: string; divisor: number } | null {\n  if (expr.type !== \"BinaryExpr\" || expr.op !== \"%\") return null;\n  const field = asFieldPath(expr.left);\n  if (field === null) return null;\n  if (!isIntegerLiteral(expr.right)) return null;\n  return { field, divisor: (expr.right as { type: \"NumberLiteral\"; value: number }).value };\n}\n\n/**\n * BSON type aliases accepted by MongoDB's `$type` query operator. Restricting\n * the peephole to this set avoids emitting a query that MongoDB would reject\n * at parse time. \"number\" is included because MQL accepts it as a synonym for\n * the int/long/double/decimal group in the query-doc form (even though the\n * aggregation `$type` expression never *returns* \"number\").\n */\nconst BSON_TYPE_ALIASES: ReadonlySet<string> = new Set([\n  \"double\",\n  \"string\",\n  \"object\",\n  \"array\",\n  \"binData\",\n  \"undefined\",\n  \"objectId\",\n  \"bool\",\n  \"date\",\n  \"null\",\n  \"regex\",\n  \"dbPointer\",\n  \"javascript\",\n  \"symbol\",\n  \"javascriptWithScope\",\n  \"int\",\n  \"timestamp\",\n  \"long\",\n  \"decimal\",\n  \"minKey\",\n  \"maxKey\",\n  \"number\",\n]);\n\n/**\n * JS's `typeof` returns `\"boolean\"`, but MongoDB's `$type` query operator uses\n * `\"bool\"` \u2014 so accept either spelling and emit the BSON form. Other JS-only\n * typeof returns (`\"function\"`, `\"symbol\"`, `\"bigint\"`) have no clean BSON\n * analogue and fall through to `$expr`.\n */\nconst JS_TO_BSON_TYPE: ReadonlyMap<string, string> = new Map([[\"boolean\", \"bool\"]]);\n\nfunction translateTypeofPredicate(left: Expr, right: Expr, op: \"===\" | \"!==\"): Record<string, unknown> | null {\n  const oriented = orientTypeofAndString(left, right);\n  if (oriented === null) return null;\n  const { field, alias: rawAlias } = oriented;\n  const alias = JS_TO_BSON_TYPE.get(rawAlias) ?? rawAlias;\n  if (!BSON_TYPE_ALIASES.has(alias)) return null;\n  return fieldQueryOrNegated(field, { $type: alias }, op);\n}\n\nfunction orientTypeofAndString(left: Expr, right: Expr): { field: string; alias: string } | null {\n  const lt = asTypeofFieldPath(left);\n  if (lt !== null && right.type === \"StringLiteral\") {\n    return { field: lt, alias: right.value };\n  }\n  const rt = asTypeofFieldPath(right);\n  if (rt !== null && left.type === \"StringLiteral\") {\n    return { field: rt, alias: left.value };\n  }\n  return null;\n}\n\nfunction asTypeofFieldPath(expr: Expr): string | null {\n  if (expr.type !== \"TypeofExpr\") return null;\n  return asFieldPath(expr.operand);\n}\n\nfunction translateEquality(\n  left: Expr,\n  right: Expr,\n  op: \"===\" | \"==\" | \"!==\" | \"!=\",\n  ctx: TranslateCtx,\n): Record<string, unknown> | null {\n  // `==` / `!=` are restricted to comparisons against null (loose null check).\n  // Validation lives in codegen \u2014 here we just don't translate them so the\n  // body falls through to $expr, which then surfaces the codegen error.\n  if (op === \"==\" || op === \"!=\") {\n    if (left.type !== \"NullLiteral\" && right.type !== \"NullLiteral\") return null;\n    return translateLooseNull(left, right, op);\n  }\n  // Strict equality (`===` / `!==`) against null gets `$type: \"null\"` so the\n  // match excludes missing-field docs, matching JS semantics.\n  if (left.type === \"NullLiteral\" || right.type === \"NullLiteral\") {\n    return translateStrictNull(left, right, op);\n  }\n  const oriented = orientFieldLiteral(left, right, (e) => anyEqualityLiteral(e, ctx));\n  if (oriented === null) return null;\n  const { field, value } = oriented;\n  if (op === \"===\") return { [field]: value };\n  return { [field]: { $ne: value } };\n}\n\nfunction translateLooseNull(left: Expr, right: Expr, op: \"==\" | \"!=\"): Record<string, unknown> | null {\n  const fieldExpr = left.type === \"NullLiteral\" ? right : left;\n  const field = asFieldPath(fieldExpr);\n  if (field === null) return null;\n  // Query language `{ field: null }` already matches null OR missing, which is\n  // exactly the loose semantics. Keep the index-friendly shape unchanged.\n  if (op === \"==\") return { [field]: null };\n  return { [field]: { $ne: null } };\n}\n\nfunction translateStrictNull(left: Expr, right: Expr, op: \"===\" | \"!==\"): Record<string, unknown> | null {\n  const fieldExpr = left.type === \"NullLiteral\" ? right : left;\n  const field = asFieldPath(fieldExpr);\n  if (field === null) return null;\n  // `$type: \"null\"` matches only docs where the field is the BSON null type \u2014\n  // missing fields are excluded, matching JS strict equality.\n  if (op === \"===\") return { [field]: { $type: \"null\" } };\n  return { [field]: { $not: { $type: \"null\" } } };\n}\n\nfunction translateOrderedCompare(\n  left: Expr,\n  right: Expr,\n  op: \">\" | \">=\" | \"<\" | \"<=\",\n  ctx: TranslateCtx,\n): Record<string, unknown> | null {\n  const leftField = asFieldPath(left);\n  const rightField = asFieldPath(right);\n  let field: string;\n  let value: unknown;\n  let effectiveOp: \">\" | \">=\" | \"<\" | \"<=\" = op;\n  if (leftField !== null && rightField === null) {\n    const lit = anyOrderedLiteral(right, ctx);\n    if (lit === null) return null;\n    field = leftField;\n    value = lit.value;\n  } else if (leftField === null && rightField !== null) {\n    const lit = anyOrderedLiteral(left, ctx);\n    if (lit === null) return null;\n    field = rightField;\n    value = lit.value;\n    effectiveOp = flipOrderedOp(op);\n  } else {\n    return null;\n  }\n  return { [field]: { [orderedOpToMql(effectiveOp)]: value } };\n}\n\nfunction orientFieldLiteral(\n  left: Expr,\n  right: Expr,\n  getLit: (e: Expr) => { value: unknown } | null,\n): { field: string; value: unknown } | null {\n  const leftField = asFieldPath(left);\n  if (leftField !== null) {\n    const rightLit = getLit(right);\n    if (rightLit !== null) return { field: leftField, value: rightLit.value };\n  }\n  const rightField = asFieldPath(right);\n  if (rightField !== null) {\n    const leftLit = getLit(left);\n    if (leftLit !== null) return { field: rightField, value: leftLit.value };\n  }\n  return null;\n}\n\nfunction isEqualityOp(op: BinaryOp): op is \"===\" | \"==\" | \"!==\" | \"!=\" {\n  return op === \"===\" || op === \"==\" || op === \"!==\" || op === \"!=\";\n}\n\nfunction isOrderedOp(op: BinaryOp): op is \">\" | \">=\" | \"<\" | \"<=\" {\n  return op === \">\" || op === \">=\" || op === \"<\" || op === \"<=\";\n}\n\nfunction orderedOpToMql(op: \">\" | \">=\" | \"<\" | \"<=\"): string {\n  return mqlForBinaryOp(op);\n}\n\nfunction flipOrderedOp(op: \">\" | \">=\" | \"<\" | \"<=\"): \">\" | \">=\" | \"<\" | \"<=\" {\n  if (op === \">\") return \"<\";\n  if (op === \">=\") return \"<=\";\n  if (op === \"<\") return \">\";\n  return \">=\";\n}\n\n/**\n * Accept any primitive literal jsmql can compare with `===` / `!==`. Arrays,\n * regexes, and BigInts are deliberately excluded:\n *   - Array literals would trigger query-language array-element matching, a\n *     semantic divergence too sharp to apply silently.\n *   - Regex literals belong in `.match()` / `.test()`; raw regex equality\n *     isn't a thing in jsmql today.\n *   - BigInt literals compile to `{ $toLong: \"...\" }` in aggregation form,\n *     which the query language doesn't recognise as a value.\n *\n * `NewDate` (and `Date.UTC` inside `new Date(...)`) is accepted *when its\n * arguments are all compile-time literals* \u2014 the value is then folded to a\n * real JS `Date` instance. The aggregation form `{ $toDate: \"...\" }` is NOT\n * accepted as a query-doc value, because MongoDB's query language treats it\n * as a literal subdocument key, not an evaluable expression.\n */\nfunction anyEqualityLiteral(expr: Expr, ctx: TranslateCtx): { value: unknown } | null {\n  switch (expr.type) {\n    case \"NumberLiteral\":\n      return { value: expr.value };\n    case \"StringLiteral\":\n      return { value: expr.value };\n    case \"BooleanLiteral\":\n      return { value: expr.value };\n    case \"NullLiteral\":\n      return { value: null };\n    case \"ParamRef\":\n      return paramRefAsLiteral(expr, ctx, /*orderedOnly*/ false);\n    case \"NewDate\":\n      return evaluateStaticDate(expr);\n    default:\n      return null;\n  }\n}\n\n/**\n * Ordered comparisons (`>`, `<`, `>=`, `<=`) only make sense against numbers,\n * strings, and dates. Booleans and nulls are almost certainly user bugs in\n * this position \u2014 let them fall through to $expr so the (rare) intentional\n * case still works. `NewDate` with all-literal args folds to a `Date` value,\n * which BSON compares as a date \u2014 index-friendly form for the common\n * `$.createdAt >= new Date(\"\u2026\")` pattern.\n */\nfunction anyOrderedLiteral(expr: Expr, ctx: TranslateCtx): { value: unknown } | null {\n  switch (expr.type) {\n    case \"NumberLiteral\":\n      return { value: expr.value };\n    case \"StringLiteral\":\n      return { value: expr.value };\n    case \"ParamRef\":\n      return paramRefAsLiteral(expr, ctx, /*orderedOnly*/ true);\n    case \"NewDate\":\n      return evaluateStaticDate(expr);\n    default:\n      return null;\n  }\n}\n\n/**\n * Compile-time-evaluate a `new Date(...)` (or `new Date(Date.UTC(...))`) when\n * all arguments are themselves number/string literals. Returns the resulting\n * `Date` so the translator can place it directly as a query-doc value \u2014\n * MongoDB's driver and shell both accept BSON `Date` instances on the RHS of\n * `$gte` / `$gt` / `$lt` / `$lte` / equality, which is what makes the index\n * usable.\n *\n * Cases that intentionally fall through to `$expr` (return null):\n *   - `new Date()` \u2014 codegens to `{ $toDate: \"$$NOW\" }` and must evaluate at\n *     query time. Folding at compile time would silently freeze the timestamp\n *     the user expected to be \"now-when-this-query-runs\".\n *   - any non-literal argument (field ref, operator call, method call, \u2026) \u2014\n *     can't be evaluated without runtime data.\n *   - any combination that produces `Invalid Date` \u2014 surface as `$expr` so\n *     the failure is visible at query time rather than as a silently bogus\n *     filter that matches nothing.\n */\nfunction evaluateStaticDate(expr: Expr & { type: \"NewDate\" }): { value: Date } | null {\n  const args = expr.args;\n  if (args.length === 0) return null;\n  if (args.length === 1) {\n    const arg = args[0];\n    if (arg.type === \"DateUTC\") {\n      const utcArgs = staticNumberArgs(arg.args);\n      if (utcArgs === null) return null;\n      const ms = (Date.UTC as (...a: number[]) => number)(...utcArgs);\n      return finalizeDate(new Date(ms));\n    }\n    if (arg.type === \"NumberLiteral\") return finalizeDate(new Date(arg.value));\n    if (arg.type === \"StringLiteral\") return finalizeDate(new Date(arg.value));\n    return null;\n  }\n  const numericArgs = staticNumberArgs(args);\n  if (numericArgs === null) return null;\n  return finalizeDate(new Date(...(numericArgs as [number, number, ...number[]])));\n}\n\nfunction staticNumberArgs(args: Expr[]): number[] | null {\n  const out: number[] = [];\n  for (const a of args) {\n    if (a.type !== \"NumberLiteral\") return null;\n    out.push(a.value);\n  }\n  return out;\n}\n\nfunction finalizeDate(d: Date): { value: Date } | null {\n  if (Number.isNaN(d.getTime())) return null;\n  return { value: d };\n}\n\n/**\n * If a `ParamRef` resolves to a function-form parameter binding, return its\n * substituted value as if it were a literal. The `orderedOnly` flag keeps the\n * type-divergence rules from `anyOrderedLiteral` honest: booleans and nulls\n * are almost certainly user bugs when used as `>` / `<` operands, so we let\n * them fall through to `$expr` instead of silently translating.\n */\nfunction paramRefAsLiteral(\n  expr: Expr & { type: \"ParamRef\" },\n  ctx: TranslateCtx,\n  orderedOnly: boolean,\n): { value: unknown } | null {\n  if (!ctx.bindings?.has(expr.name)) return null;\n  const value = ctx.bindings.get(expr.name);\n  if (orderedOnly) {\n    // Ordered comparisons accept numbers, strings, and `Date` instances \u2014\n    // `Date` so `jsmql.compile(($) => $.createdAt >= params.cutoff)({ cutoff: new Date(\u2026) })`\n    // emits index-friendly field-form instead of $expr.\n    if (typeof value !== \"number\" && typeof value !== \"string\" && !(value instanceof Date)) return null;\n  } else {\n    // Equality-side: accept the same primitives the literal-AST path accepts,\n    // plus BSON-comparable instance values (Date, RegExp, Buffer / Uint8Array,\n    // and duck-typed ObjectId). Refuses plain arrays/objects \u2014 those would\n    // silently switch on query-language array-element matching or be matched\n    // as literal subdocs, both surprising.\n    if (!isQueryDocLiteralValue(value)) return null;\n  }\n  return { value };\n}\n\nfunction isQueryDocLiteralValue(value: unknown): boolean {\n  if (value === null) return true;\n  const t = typeof value;\n  if (t === \"number\" || t === \"string\" || t === \"boolean\") return true;\n  return isOpaqueBsonValue(value);\n}\n\n/**\n * Reconstruct a MongoDB field path string from `$.a.b.c`-style AST chains.\n * Matches the (private) logic in codegen.ts:asFieldPath, but returns the bare\n * dotted path without the leading `$` \u2014 query-document keys use field names,\n * not aggregation field references.\n *\n * Returns null for anything that isn't a static field path: index access,\n * method calls, lambda param refs, operator calls, etc.\n */\nfunction asFieldPath(expr: Expr): string | null {\n  if (expr.type === \"FieldRef\") return expr.path;\n  if (expr.type === \"MemberAccess\") {\n    const base = asFieldPath(expr.object);\n    if (base !== null) return `${base}.${expr.member}`;\n  }\n  return null;\n}\n", "// Collection-union translation: lowers `$$.push(args...)` statements into\n// MongoDB `$unionWith` stages.\n//\n// `$$` is the current-collection context-ref. `.push(...)` is the JS array\n// mutation that appends items to the end of an array \u2014 exactly the\n// semantic of `$unionWith` (append documents from another collection /\n// pipeline / `$documents` block to the current stream). Symmetry with\n// `Array.prototype.push` means the spread (`...`) rule is JS-faithful:\n//\n//   - `.push(...arr)` spreads an array (`.filter(pred)` or bare collection).\n//   - `.push(scalar)` pushes one value (`.find(pred)` or `{ inline doc }`).\n//\n// `.find(...)` returns a single doc \u2192 no spread. `.filter(...)` returns an\n// array \u2192 must be spread. Inline objects are scalars \u2192 no spread. Each\n// shape lowers to a distinct `$unionWith` stage body; consecutive inline-doc\n// arguments batch into one `$documents` sub-pipeline (fewer stages, identical\n// behaviour). Source-order is preserved across the whole arg list \u2014 a\n// document pushed before a collection appears first in the union, and vice\n// versa.\n//\n// `$unionWith` has no `let` slot (unlike `$lookup`), so a predicate that\n// references the local document (`$.x`) is a compile-time error \u2014 moving the\n// local filter to a `$match` stage before the push is the documented fix.\n//\n// Statement-only: `$$.push(...)` emits one or more stages and produces no\n// value. Using it on a RHS / as a value is rejected \u2014 `CollectionRef`\n// codegen surfaces the bare-reference error for those misuses.\n//\n// See `docs/specs/union-stage.md` for the full design and the error catalog.\n\nimport type { Expr, CallArg, Pipeline, PipelineStmt, UpdateFilter, UpdateOp } from \"./ast.ts\";\nimport { CodegenError, EMPTY_CTX, freshSubPipelineCtx, generateWithCtx, type GenerateCtx } from \"./codegen.ts\";\nimport {\n  detectLookupCall,\n  extractLookupTarget,\n  lowerLambdaPredicate,\n  validateLookupShape,\n  type LookupCall,\n  type SubPipelineLowerer,\n} from \"./lookup-translation.ts\";\n\n// Aliases for the few AST variants we touch directly.\ntype SpreadElement = Extract<CallArg, { type: \"SpreadElement\" }>;\n\n// \u2500\u2500 Detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type UnionPushCall = {\n  /** Position of the `$$` receiver token. */\n  pos: number;\n  /** Position of the `.push(...)` call site (for argument-level errors). */\n  callPos: number;\n  /** Raw args; lowering re-walks them so each one's pos is preserved for errors. */\n  args: CallArg[];\n};\n\n/**\n * Recognise a `$$.push(...)` MethodCall \u2014 the union entry point. Returns\n * `null` for anything else, including method calls on `CollectionRef` that\n * use a method other than `push`. Those other methods (`.filter`, `.map`,\n * `.slice`, \u2026 as well as unknown names) are handled by the bare-statement\n * stream-chain branch in `pipeline.ts` (`applyStreamMethods`), which lowers\n * the valid ones and emits an actionable registry error for the rest.\n */\nexport function detectUnionPush(expr: Expr): UnionPushCall | null {\n  if (expr.type !== \"MethodCall\") return null;\n  if (expr.method !== \"push\") return null;\n  if (expr.object.type !== \"CollectionRef\") return null;\n  return { pos: expr.object.pos, callPos: expr.pos, args: expr.args };\n}\n\n/**\n * Cheap recursive walk: does `node` (or any sub-tree thereof) contain a\n * `$$.push(...)` call? Used by mode-gates in `index.ts` to pre-reject the\n * statement-only union syntax in Filter / `jsmql.expr` / `jsmql.update`\n * modes with an actionable error.\n *\n * Defaults `ctx` to `EMPTY_CTX` for mode-gate call sites without a\n * meaningful context \u2014 the detection doesn't depend on ctx (push doesn't\n * have any bracket-bound forms today), but the parameter is kept so the\n * shape mirrors `containsLookupCall` and survives if we add binding-aware\n * shapes later.\n */\nexport function containsUnionPush(node: Expr | Pipeline | UpdateFilter, _ctx: GenerateCtx = EMPTY_CTX): boolean {\n  return walkContainsPush(node);\n}\n\nfunction walkContainsPush(node: Expr | Pipeline | UpdateFilter | PipelineStmt | UpdateOp): boolean {\n  if (node.type === \"Pipeline\") return node.stmts.some(walkContainsPush);\n  if (node.type === \"UpdateFilter\") return node.ops.some(walkContainsPush);\n  if (node.type === \"AssignExpr\") return walkContainsPush(node.value);\n  if (node.type === \"DeleteStmt\") return false;\n  if (node.type === \"LetDecl\") return walkContainsPush(node.value);\n  const expr = node;\n  if (detectUnionPush(expr) !== null) return true;\n  if (expr.type === \"MethodCall\") {\n    if (walkContainsPush(expr.object)) return true;\n    return walkArgsContainPush(expr.args);\n  }\n  if (expr.type === \"CallExpression\") {\n    if (walkContainsPush(expr.callee)) return true;\n    return walkArgsContainPush(expr.args);\n  }\n  if (expr.type === \"OperatorCall\" || expr.type === \"MathCall\" || expr.type === \"ObjectCall\") {\n    return walkArgsContainPush(expr.args);\n  }\n  if (expr.type === \"MemberAccess\") return walkContainsPush(expr.object);\n  if (expr.type === \"IndexAccess\") return walkContainsPush(expr.object) || walkContainsPush(expr.index);\n  if (expr.type === \"BinaryExpr\") return walkContainsPush(expr.left) || walkContainsPush(expr.right);\n  if (expr.type === \"UnaryExpr\") return walkContainsPush(expr.operand);\n  if (expr.type === \"TernaryExpr\") {\n    return walkContainsPush(expr.condition) || walkContainsPush(expr.consequent) || walkContainsPush(expr.alternate);\n  }\n  if (expr.type === \"Lambda\") {\n    if (expr.body !== undefined) return walkContainsPush(expr.body);\n    if (expr.block !== undefined) return walkContainsPush(expr.block);\n    return false;\n  }\n  if (expr.type === \"ArrayLiteral\") {\n    for (const el of expr.elements) {\n      if (el.type === \"SpreadElement\") {\n        if (walkContainsPush(el.argument)) return true;\n      } else if (walkContainsPush(el)) {\n        return true;\n      }\n    }\n    return false;\n  }\n  if (expr.type === \"ObjectLiteral\") {\n    for (const entry of expr.entries) {\n      if (entry.type === \"SpreadElement\") {\n        if (walkContainsPush(entry.argument)) return true;\n      } else {\n        if (entry.key.kind === \"computed\" && walkContainsPush(entry.key.expr)) return true;\n        if (walkContainsPush(entry.value)) return true;\n      }\n    }\n    return false;\n  }\n  if (expr.type === \"TemplateLiteral\") return expr.expressions.some(walkContainsPush);\n  if (expr.type === \"TypeofExpr\") return walkContainsPush(expr.operand);\n  if (expr.type === \"NewDate\") return expr.args.some(walkContainsPush);\n  if (expr.type === \"NewSet\") return expr.arg ? walkContainsPush(expr.arg) : false;\n  if (expr.type === \"TypeCast\") return walkContainsPush(expr.arg);\n  if (expr.type === \"ArrayFrom\")\n    return walkContainsPush(expr.input) || (expr.mapFn ? walkContainsPush(expr.mapFn) : false);\n  if (expr.type === \"NumberStatic\") return walkContainsPush(expr.arg);\n  if (expr.type === \"DateUTC\") return expr.args.some(walkContainsPush);\n  return false;\n}\n\nfunction walkArgsContainPush(args: CallArg[]): boolean {\n  for (const a of args) {\n    if (a.type === \"SpreadElement\") {\n      if (walkContainsPush(a.argument)) return true;\n    } else if (walkContainsPush(a)) {\n      return true;\n    }\n  }\n  return false;\n}\n\n// \u2500\u2500 Lowering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Walk the `$$.push(arg1, arg2, \u2026)` arg list and emit one or more\n * `$unionWith` stages. Consecutive inline-doc args (`{...}`) batch into a\n * single `$documents`-form `$unionWith`. Collection-sourced args\n * (`...$$$.coll[.filter(pred)]`, `$$$.coll.find(pred)`) each emit their own\n * stage. Source order is preserved across the whole list: e.g. one inline\n * doc followed by a spread collection followed by another inline doc\n * produces three stages in that order.\n *\n * Rejections (raised on the offending arg's `pos`):\n *\n *   - `...$$$.coll.find(pred)` \u2014 spreading a scalar (JS would TypeError);\n *      \"drop the `...`\".\n *   - `$$$.coll.filter(pred)` without `...` \u2014 pushing an array as one doc\n *      (silent footgun in JS too); \"add the `...`\".\n *   - Predicate references `$.x` \u2014 `$unionWith` has no `let`; move the\n *      local-doc filter to a `$match` before the push.\n *   - Non-document argument (scalar literal, arithmetic expression, etc.) \u2014\n *      collections only hold documents.\n *   - Wrong method on `$$` (anything other than `.push`) \u2014 surfaced earlier\n *      by `validateUnionPushShape`.\n */\nexport function lowerUnionPush(call: UnionPushCall, outerCtx: GenerateCtx, lowerBlock: SubPipelineLowerer): object[] {\n  if (call.args.length === 0) {\n    throw new CodegenError(\n      `$$.push() requires at least one argument \u2014 a document literal (\\`{...}\\`), ` +\n        `a spread of \\`$$$.<coll>[.filter(pred)]\\`, or \\`$$$.<coll>.find(pred)\\`.`,\n      call.callPos,\n    );\n  }\n  const stages: object[] = [];\n  let inlineBatch: unknown[] = [];\n\n  const flushInline = () => {\n    if (inlineBatch.length === 0) return;\n    stages.push({ $unionWith: { pipeline: [{ $documents: inlineBatch }] } });\n    inlineBatch = [];\n  };\n\n  for (const arg of call.args) {\n    if (arg.type === \"SpreadElement\") {\n      flushInline();\n      stages.push(lowerSpreadArg(arg, outerCtx, lowerBlock));\n      continue;\n    }\n    // Non-spread arg.\n    if (arg.type === \"ObjectLiteral\") {\n      // Inline doc \u2014 batch with adjacent inline docs.\n      inlineBatch.push(generateWithCtx(arg, outerCtx));\n      continue;\n    }\n    // `.find(pred)` without spread \u2192 append a single doc.\n    const lookupCall = detectLookupCall(arg, outerCtx);\n    if (lookupCall !== null) {\n      if (lookupCall.method === \"filter\") {\n        const recv = formatReceiver(lookupCall);\n        throw new CodegenError(\n          `$$.push(...) was given \\`${recv}.filter(pred)\\` without \\`...\\` \u2014 that would push the whole array as a single document. ` +\n            `Use \\`$$.push(...${recv}.filter(pred))\\` to append every matching document, ` +\n            `or switch to \\`.find(pred)\\` if you meant the first match.`,\n          arg.pos,\n        );\n      }\n      // .find \u2014 single-doc append.\n      validateLookupShape(arg);\n      flushInline();\n      stages.push(lowerFindAsUnion(lookupCall, outerCtx, lowerBlock));\n      continue;\n    }\n    // Anything else is invalid.\n    rejectNonDocumentArg(arg);\n  }\n  flushInline();\n  return stages;\n}\n\n/**\n * Lower one `...inner` argument inside `$$.push(...)`. Accepted shapes for\n * `inner`: bare `$$$.coll` (no method, short-form `$unionWith`), or\n * `$$$.coll.filter(pred)` (pipeline-form `$unionWith`). Cross-DB variants\n * (`$$$$.<db>.<coll>[.filter(pred)]`) lower to the Atlas Data Federation\n * `from: { db, coll }` shape. `.find(pred)` is rejected here (scalar; can't\n * be spread).\n */\nfunction lowerSpreadArg(arg: SpreadElement, outerCtx: GenerateCtx, lowerBlock: SubPipelineLowerer): object {\n  const inner = arg.argument;\n  // .find(pred) inside a spread \u2014 JS-faithful: spreading a scalar is a TypeError.\n  if (inner.type === \"MethodCall\" && inner.method === \"find\" && inner.object.type !== \"FieldRef\") {\n    const lookup = detectLookupCall(inner, outerCtx);\n    if (lookup !== null) {\n      const recv = formatReceiver(lookup);\n      throw new CodegenError(\n        `$$.push(...arg) was given \\`...${recv}.find(pred)\\` \u2014 \\`.find\\` returns a single document, not an array, so spreading isn't meaningful (JS would \\`TypeError\\`). ` +\n          `Drop the \\`...\\` to append the matched document, or switch to \\`...${recv}.filter(pred)\\` to append every match.`,\n        inner.pos,\n      );\n    }\n  }\n  // `.filter(pred)` \u2192 pipeline-form `$unionWith`.\n  const lookup = detectLookupCall(inner, outerCtx);\n  if (lookup !== null && lookup.method === \"filter\") {\n    validateLookupShape(inner);\n    return buildUnionWith(lookup, outerCtx, lowerBlock, /* limitOne */ false);\n  }\n  // Bare `$$$.coll` (no method): short-form `{ $unionWith: \"<coll>\" }`.\n  const target = extractLookupTarget(inner, outerCtx);\n  if (target !== null) {\n    if (target.db !== undefined) {\n      return { $unionWith: { coll: { db: target.db, coll: target.collection } } };\n    }\n    return { $unionWith: target.collection };\n  }\n  // Catch-all: malformed shapes that still parsed (e.g. `...someVar`).\n  // Surface the same actionable hint that `lowerUnionPush` uses for non-spread args.\n  throw new CodegenError(\n    `$$.push(...arg) \u2014 spread argument must be \\`$$$.<coll>\\`, \\`$$$.<coll>.filter(pred)\\`, or the cross-DB \\`$$$$.<db>.<coll>[.filter(pred)]\\` form. ` +\n      `Spreading anything else isn't meaningful for collection union.`,\n    inner.pos,\n  );\n}\n\n/**\n * Lower a `.find(pred)` argument (no spread) into a `$unionWith` whose\n * sub-pipeline ends with `$limit: 1` \u2014 appending zero-or-one document, the\n * JS-faithful counterpart to the `$lookup + $first` lowering used when\n * `.find` is consumed as a value.\n */\nfunction lowerFindAsUnion(call: LookupCall, outerCtx: GenerateCtx, lowerBlock: SubPipelineLowerer): object {\n  return buildUnionWith(call, outerCtx, lowerBlock, /* limitOne */ true);\n}\n\nfunction buildUnionWith(\n  call: LookupCall,\n  outerCtx: GenerateCtx,\n  lowerBlock: SubPipelineLowerer,\n  limitOne: boolean,\n): object {\n  const pipeline = translateUnionPredicate(call, outerCtx, lowerBlock);\n  if (limitOne) pipeline.push({ $limit: 1 });\n  const from: string | { db: string; coll: string } =\n    call.db !== undefined ? { db: call.db, coll: call.collection } : call.collection;\n  if (pipeline.length === 0) {\n    // Vacuous predicate (e.g. a block body with no stages) collapses to short\n    // form. Only reachable for `.filter` with an empty block body \u2014 `.find`\n    // always emits at least the `$limit: 1` we just pushed.\n    return { $unionWith: from };\n  }\n  if (typeof from === \"string\") {\n    return { $unionWith: { coll: from, pipeline } };\n  }\n  return { $unionWith: { coll: from, pipeline } };\n}\n\n/**\n * Translate a `.filter(pred)` / `.find(pred)` lambda into the sub-pipeline\n * body for `$unionWith.pipeline`. Differs from the `$lookup`-side\n * `translatePredicate` in two ways:\n *\n *   1. `$unionWith` has no `let` slot, so any `$.x` reference (= a let-var\n *      auto-extracted from the predicate body) is a compile-time error.\n *\n *   2. Expression-body predicates that don't reference the local doc are\n *      routed through the same `translateMatchBody` engine `$match` uses,\n *      so the inner `$match` emits index-friendly query syntax\n *      (`{ field: value }`) instead of always wrapping in `{ $expr: \u2026 }`.\n *      The query planner can use foreign-collection indexes on the\n *      translated half. Untranslatable residuals still ride in `$expr`.\n */\nfunction translateUnionPredicate(call: LookupCall, outerCtx: GenerateCtx, lowerBlock: SubPipelineLowerer): object[] {\n  // Shared expr-or-block predicate lowering (see `lowerLambdaPredicate`). The\n  // foreign-doc paths are rewritten to bare `FieldRef`s, then expression bodies\n  // run through the same translator `$match` uses; the sub-pipeline gets a fresh\n  // ctx (outer lets don't cross the boundary). `$unionWith` has no `let` slot, so\n  // a predicate that references the local doc (`$.<field>`) is rejected.\n  return lowerLambdaPredicate(call.lambda, outerCtx, lowerBlock, {\n    freshCtx: freshSubPipelineCtx,\n    onLocalRef: () => {\n      throw new CodegenError(correlatedPushPredicateMessage(call), call.lambda.pos);\n    },\n    missingBody: () => {\n      throw new CodegenError(\n        `.${call.method}(predicate) lambda is missing a body \u2014 internal parser bug; please report.`,\n        call.lambda.pos,\n      );\n    },\n  });\n}\n\nfunction correlatedPushPredicateMessage(call: LookupCall): string {\n  const recv = formatReceiver(call);\n  return (\n    `$$.push(...${recv}.${call.method}(pred)) \u2014 predicate references the local document (\\`$.<field>\\`), ` +\n    `but MongoDB's \\`$unionWith\\` has no \\`let\\` slot. The union sub-pipeline can only reference foreign-document fields. ` +\n    `Move the local-doc filter to a \\`$match(...)\\` stage before \\`$$.push(...)\\`.`\n  );\n}\n\nfunction rejectNonDocumentArg(arg: Expr): never {\n  // Best-effort hint: name the offending shape if we recognise it.\n  let hint = \"\";\n  if (arg.type === \"NumberLiteral\" || arg.type === \"StringLiteral\" || arg.type === \"BooleanLiteral\") {\n    hint = ` Got a ${arg.type.replace(/Literal$/, \"\").toLowerCase()} literal \u2014 collections only hold documents.`;\n  } else if (arg.type === \"NullLiteral\") {\n    hint = \" Got `null` \u2014 collections only hold documents.\";\n  } else if (arg.type === \"FieldRef\" || arg.type === \"ParamRef\") {\n    hint =\n      \" To append a runtime-supplied document, accept it as a `jsmql.compile` parameter binding and wrap as `$$.push($.<doc>)`. \" +\n      \"Note: $$.push doesn't accept bare field paths \u2014 wrap inside an inline `{ ... }` if you want to project specific fields.\";\n  }\n  throw new CodegenError(\n    `$$.push(...) argument must be a document literal (\\`{ ... }\\`), a \\`$$$.<coll>.find(pred)\\` scalar, ` +\n      `or a spread of \\`$$$.<coll>[.filter(pred)]\\`.${hint}`,\n    (arg as { pos?: number }).pos ?? 0,\n  );\n}\n\nfunction formatReceiver(call: LookupCall): string {\n  return call.db !== undefined ? `$$$$.${call.db}.${call.collection}` : `$$$.${call.collection}`;\n}\n", "// Stream-method registry: the chainable JS array-method vocabulary that\n// extends a `$$ = $$.<chain>;` or `$$ = $$$.<coll>.<chain>;` RHS into\n// pipeline stages. One entry per method, each declaring its arg-shape\n// validator and its lowering to MQL stages. Walked by pipeline.ts \u2014\n// adding a method here makes it usable in both stream contexts.\n//\n// See docs/specs/stream-methods.md for the design and the per-method\n// shape/lowering/error table.\n\nimport type { ArrayElement, CallArg, Expr } from \"./ast.ts\";\nimport { CodegenError, generateWithCtx, type GenerateCtx } from \"./codegen.ts\";\nimport {\n  extractLetsFromExpr,\n  extractLookupCalls,\n  type SlotAllocator,\n  type SubPipelineLowerer,\n} from \"./lookup-translation.ts\";\nimport { containsUnionPush } from \"./union-translation.ts\";\nimport { lowerUnionPush } from \"./union-translation.ts\";\n\ntype LambdaNode = Extract<Expr, { type: \"Lambda\" }>;\n\nexport type StreamMethodResult = {\n  /** Stages this method contributes, appended to the surrounding chain. */\n  stages: object[];\n  /**\n   * True if the emitted stages replace the document and drop in-scope `let`\n   * bindings. Threaded back to the caller so the outer pipeline ctx can\n   * clear the let scope. Defaults to false.\n   */\n  clearLets?: boolean;\n  /**\n   * If true, the caller drops the *immediately preceding* stage from the\n   * accumulator before appending `stages`. Used by methods like\n   * `.toReversed()` that rewrite the preceding `$sort` rather than appending\n   * a new stage. Defaults to false.\n   */\n  replacesPreviousStage?: boolean;\n};\n\nexport type StreamMethodDef = {\n  /** JS method name (e.g. \"slice\"). */\n  name: string;\n  /**\n   * Validate the call's arg shape. Throw `CodegenError` (with `.pos`) for\n   * any rejection branch. Called before `lower`; lowering may assume the\n   * args have the shape the validator accepts.\n   */\n  validate: (args: readonly CallArg[], callPos: number) => void;\n  /**\n   * Produce the stages this method contributes.\n   *\n   * `prevStages` is the read-only view of stages the chain has emitted so\n   * far in this context (outer pipeline for `$$` chains; `$unionWith`\n   * sub-pipeline body for `$$$.<coll>` chains). Methods that don't need to\n   * peek (`.slice`, `.map`, \u2026) simply ignore it. Methods that do\n   * (`.toReversed`) can read the last stage and return\n   * `replacesPreviousStage: true` so the caller drops it before appending.\n   *\n   * `allocSlot` allocates a fresh `__jsmql.__lookup<N>` slot from the\n   * surrounding pipeline's tracker \u2014 used by methods that need to\n   * materialise embedded `$$$.<coll>.find/filter(...)` lookups (e.g.\n   * `.map`'s body). Each call to `allocSlot()` marks the pipeline as\n   * having used the namespace so the trailing `$unset: \"__jsmql\"` cleanup\n   * is emitted. `inSubPipeline` is true when the chain is being lowered\n   * inside a `$unionWith.pipeline` body (i.e. the `$$$.<coll>.<chain>` head);\n   * methods that would otherwise produce nested `$lookup` stages use this\n   * flag to surface the standard \"nested lookup not yet supported\" error.\n   */\n  lower: (\n    args: readonly CallArg[],\n    ctx: GenerateCtx,\n    callPos: number,\n    lowerBlock: SubPipelineLowerer,\n    prevStages: readonly object[],\n    allocSlot: SlotAllocator,\n    inSubPipeline: boolean,\n  ) => StreamMethodResult;\n};\n\n// \u2500\u2500 .slice(start, end?) \u2192 $skip + $limit \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Non-negative integer literals only. `start === 0` skips the `$skip` emission\n// (no-op); a missing `end` skips the `$limit` emission (slice-from-start).\n//\n// JS `arr.slice(start, end)` returns elements at indices [start, end). The\n// stream equivalent skips `start` documents from the head and (optionally)\n// limits the remaining count to `end - start`.\nconst SLICE: StreamMethodDef = {\n  name: \"slice\",\n  validate(args, callPos) {\n    if (args.length === 0 || args.length > 2) {\n      throw new CodegenError(`.slice(start[, end]) takes 1 or 2 arguments, got ${args.length}.`, callPos);\n    }\n    for (const arg of args) {\n      if (arg.type === \"SpreadElement\") {\n        throw new CodegenError(`.slice(start[, end]) does not accept spread arguments.`, arg.pos);\n      }\n      if (arg.type !== \"NumberLiteral\") {\n        throw new CodegenError(\n          `.slice(start[, end]) requires non-negative integer literals; got '${arg.type}'. Computed or dynamic arguments aren't supported on streams in v1 \u2014 write the literal in source.`,\n          arg.pos,\n        );\n      }\n      if (arg.value < 0 || !Number.isInteger(arg.value)) {\n        throw new CodegenError(\n          `.slice(start[, end]) requires non-negative integer literals; got ${arg.value}. Negative indices and fractional values aren't supported on streams.`,\n          arg.pos,\n        );\n      }\n    }\n    if (args.length === 2) {\n      const start = (args[0] as Extract<Expr, { type: \"NumberLiteral\" }>).value;\n      const end = (args[1] as Extract<Expr, { type: \"NumberLiteral\" }>).value;\n      if (end < start) {\n        throw new CodegenError(`.slice(start, end) requires end >= start (got start=${start}, end=${end}).`, callPos);\n      }\n    }\n  },\n  lower(args, _ctx, _callPos) {\n    const start = (args[0] as Extract<Expr, { type: \"NumberLiteral\" }>).value;\n    const stages: object[] = [];\n    if (start > 0) stages.push({ $skip: start });\n    if (args.length === 2) {\n      const end = (args[1] as Extract<Expr, { type: \"NumberLiteral\" }>).value;\n      stages.push({ $limit: end - start });\n    }\n    return { stages };\n  },\n};\n\n// \u2500\u2500 .concat(...others) \u2192 $unionWith per arg \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// JS-idiomatic alias for `$$.push(...)` in the chain context. Same arg-shape\n// rules \u2014 collections must be spread (`...$$$.coll[.filter(p)]`), inline docs\n// must not, `.find(pred)` results must not. The lowering routes through\n// `lowerUnionPush` so the two codepaths stay in lock-step (no second copy of\n// the spread / inline-doc / `.find` validation logic).\n//\n// Statement-only `$$.push(...)` continues to live in `union-translation.ts`;\n// `.concat` is purely the chain-method analogue.\nconst CONCAT: StreamMethodDef = {\n  name: \"concat\",\n  validate(args, callPos) {\n    if (args.length === 0) {\n      throw new CodegenError(\n        `.concat(...) requires at least one argument \u2014 a document literal ('{...}'), a spread of '$$$.<coll>[.filter(pred)]', or '$$$.<coll>.find(pred)'.`,\n        callPos,\n      );\n    }\n    // Per-arg shape validation lives inside `lowerUnionPush` (same engine\n    // `$$.push` uses) \u2014 running it here would duplicate the rejection branches\n    // verbatim. Defer.\n  },\n  lower(args, ctx, callPos, lowerBlock) {\n    const stages = lowerUnionPush({ pos: callPos, callPos, args: [...args] }, ctx, lowerBlock);\n    return { stages };\n  },\n};\n\n// \u2500\u2500 .map(d => <expr>) \u2192 $replaceWith \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Chain-form of the existing `$ = <expr>` statement sugar. Single-param\n// arrow only; the parameter IS the current document, so `d.x` rewrites to\n// the bare field path `$x` and `$.<field>` references are rejected (same\n// \"use the lambda parameter\" convention as `.filter`). `$$.push` calls\n// inside the body are rejected (statement-only construct, semantics don't\n// fit inside an expression-position lambda).\n//\n// `$$$.<coll>.find/filter(...)` lookups inside the body ARE supported in\n// both stream contexts. The body is post-processed through\n// `extractLookupCalls` to materialise each lookup into an\n// `__jsmql.__lookup<N>` slot ahead of the `$replaceWith`. References to\n// the outer doc (`d.<field>`) get rewritten to bare field paths via\n// `extractLetsFromExpr` BEFORE the lookup extractor runs, so the lookup\n// predicate's `extractLetsFromExpr` (called from inside\n// `translatePredicate`) sees those as `$.<field>` and hoists them to\n// `$lookup.let` slots \u2014 basic-form is preferred when the predicate is a\n// single `===` between matching paths. In the lookup-body context\n// (`$$$.<coll>.filter(p).map(...)`), the materialised `$lookup` lands as\n// a nested stage inside the outer `$unionWith.pipeline` \u2014 valid MQL,\n// since the lookup correlates against the sub-pipeline's local doc (the\n// foreign collection), not any outer-pipeline `let` binding.\nconst MAP: StreamMethodDef = {\n  name: \"map\",\n  validate(args, callPos) {\n    if (args.length !== 1) {\n      throw new CodegenError(\n        `.map(d => <expr>) takes exactly one argument (a single-parameter arrow), got ${args.length}.`,\n        callPos,\n      );\n    }\n    const arg = args[0];\n    if (arg.type === \"SpreadElement\") {\n      throw new CodegenError(`.map(...) does not accept a spread argument \u2014 pass a '(d) => <expr>' arrow.`, arg.pos);\n    }\n    if (arg.type !== \"Lambda\") {\n      throw new CodegenError(\n        `.map(d => <expr>) requires an arrow function as its argument, e.g. '.map(d => ({ id: d._id, name: d.name }))'.`,\n        arg.pos,\n      );\n    }\n    if (arg.params.length !== 1) {\n      throw new CodegenError(\n        `.map(d => <expr>) takes a single-parameter arrow (got ${arg.params.length}). MongoDB streams have no per-doc index, so '(d, i) => \u2026' isn't meaningful here.`,\n        arg.pos,\n      );\n    }\n    if (arg.body === undefined) {\n      throw new CodegenError(\n        `.map(d => <expr>) requires an expression body. Block-body arrows ('d => { \u2026 }') aren't supported here \u2014 split into separate stages ($set, $project, \u2026) instead.`,\n        arg.pos,\n      );\n    }\n  },\n  lower(args, ctx, _callPos, lowerBlock, _prevStages, allocSlot, _inSubPipeline) {\n    const lambda = args[0] as LambdaNode;\n    const param = lambda.params[0];\n    const body = lambda.body as Expr;\n    if (containsUnionPush(body)) {\n      throw new CodegenError(\n        `'$$.push(...)' inside a '.map(d => \u2026)' body isn't meaningful \u2014 '$$.push' is a statement-level form that emits '$unionWith' stages. Hoist it before the chain.`,\n        lambda.pos,\n      );\n    }\n    // Lookups inside the body are supported in both the top-level `$$` chain\n    // and the lookup-body context (`$$$.<coll>.<chain>`). In the latter,\n    // they land as a `$lookup` nested inside the outer `$unionWith.pipeline`\n    // \u2014 valid MQL; the basic-form / pipeline-form translation in\n    // `lookup-translation.ts` correlates against the sub-pipeline's local\n    // doc (the foreign collection from the outer `$unionWith`), not any\n    // outer-pipeline `let` bindings, so the let-coordination problem that\n    // blocks the general nested-lookup case doesn't apply here.\n    const { rewritten, letVars } = extractLetsFromExpr(body, param);\n    if (Object.keys(letVars).length > 0) {\n      const samplePath = Object.values(letVars)[0].replace(/^\\$+/, \"\");\n      throw new CodegenError(\n        `'$.<field>' inside '.map(d => \u2026)' isn't supported \u2014 use the lambda parameter (e.g. '${param}.${samplePath}') to reference each input document. Inside this map, the lambda parameter IS the current document.`,\n        lambda.pos,\n      );\n    }\n    // Materialise any `$$$.<coll>.find/filter(...)` lookups in the rewritten\n    // body into prologue stages. `extractLookupCalls` handles the basic-vs-\n    // pipeline-form predicate translation, auto-`let` extraction (for the\n    // outer-doc paths we just rewrote to bare `FieldRef`s), and `$first`\n    // wrapping for `.find`. When there are no lookups it returns prologue=[]\n    // and the unchanged expr.\n    const { stages: prologue, rewritten: rewritten2 } = extractLookupCalls(rewritten, ctx, allocSlot, lowerBlock);\n    const expr = generateWithCtx(rewritten2, ctx);\n    return { stages: [...prologue, { $replaceWith: expr }], clearLets: true };\n  },\n};\n\n// \u2500\u2500 .toSorted((a, b) => \u2026) \u2192 $sort \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Accepts a comparator-shape expression body built from `a.<path> - b.<path>`\n// terms (ascending), `b.<path> - a.<path>` terms (descending), and `||`\n// combining multiple terms (compound sort, source order preserved). Anything\n// else is rejected \u2014 bare `.toSorted()` (default JS string compare) included,\n// because MongoDB streams of documents have no natural ordering.\ntype ComparatorPath = { param: \"a\" | \"b\"; path: string };\n\nfunction classifyComparatorPath(expr: Expr, paramA: string, paramB: string): ComparatorPath | null {\n  let cur: Expr = expr;\n  const segments: string[] = [];\n  while (cur.type === \"MemberAccess\" || cur.type === \"IndexAccess\") {\n    if (cur.type === \"MemberAccess\") {\n      segments.unshift(cur.member);\n      cur = cur.object;\n      continue;\n    }\n    if (cur.type === \"IndexAccess\" && cur.index.type === \"StringLiteral\") {\n      segments.unshift(cur.index.value);\n      cur = cur.object;\n      continue;\n    }\n    return null;\n  }\n  if (cur.type !== \"ParamRef\") return null;\n  const which: \"a\" | \"b\" | null = cur.name === paramA ? \"a\" : cur.name === paramB ? \"b\" : null;\n  if (which === null) return null;\n  if (segments.length === 0) return null;\n  return { param: which, path: segments.join(\".\") };\n}\n\nfunction parseComparatorBody(body: Expr, paramA: string, paramB: string, callPos: number): Record<string, 1 | -1> {\n  if (body.type === \"BinaryExpr\" && body.op === \"||\") {\n    const left = parseComparatorBody(body.left, paramA, paramB, callPos);\n    const right = parseComparatorBody(body.right, paramA, paramB, callPos);\n    return { ...left, ...right };\n  }\n  if (body.type === \"BinaryExpr\" && body.op === \"-\") {\n    const leftPath = classifyComparatorPath(body.left, paramA, paramB);\n    const rightPath = classifyComparatorPath(body.right, paramA, paramB);\n    if (leftPath !== null && rightPath !== null && leftPath.path === rightPath.path) {\n      if (leftPath.param === \"a\" && rightPath.param === \"b\") return { [leftPath.path]: 1 };\n      if (leftPath.param === \"b\" && rightPath.param === \"a\") return { [leftPath.path]: -1 };\n    }\n  }\n  throw new CodegenError(\n    `.toSorted((${paramA}, ${paramB}) => \u2026) accepts only '${paramA}.<field> - ${paramB}.<field>' (ascending) or '${paramB}.<field> - ${paramA}.<field>' (descending) terms, combined with '||' for compound sorts. Other comparator shapes aren't supported on streams.`,\n    body.pos ?? callPos,\n  );\n}\n\nconst TO_SORTED: StreamMethodDef = {\n  name: \"toSorted\",\n  validate(args, callPos) {\n    if (args.length === 0) {\n      throw new CodegenError(\n        `.toSorted(<comparator>) requires a comparator arrow \u2014 MongoDB streams have no natural document ordering. Write '.toSorted((a, b) => a.<field> - b.<field>)' for ascending, 'b.<field> - a.<field>' for descending.`,\n        callPos,\n      );\n    }\n    if (args.length > 1) {\n      throw new CodegenError(`.toSorted(<comparator>) takes exactly one argument, got ${args.length}.`, callPos);\n    }\n    const arg = args[0];\n    if (arg.type === \"SpreadElement\") {\n      throw new CodegenError(`.toSorted(...) does not accept a spread argument.`, arg.pos);\n    }\n    if (arg.type !== \"Lambda\") {\n      throw new CodegenError(\n        `.toSorted(<comparator>) requires an arrow function, e.g. '.toSorted((a, b) => a.age - b.age)'.`,\n        arg.pos,\n      );\n    }\n    if (arg.params.length !== 2) {\n      throw new CodegenError(\n        `.toSorted(<comparator>) requires a two-parameter arrow '(a, b) => \u2026' (got ${arg.params.length} params).`,\n        arg.pos,\n      );\n    }\n    if (arg.body === undefined) {\n      throw new CodegenError(`.toSorted(<comparator>) requires an expression body, not a block.`, arg.pos);\n    }\n  },\n  lower(args, _ctx, callPos, _lowerBlock) {\n    const lambda = args[0] as LambdaNode;\n    const [paramA, paramB] = lambda.params;\n    const body = lambda.body as Expr;\n    const spec = parseComparatorBody(body, paramA, paramB, callPos);\n    return { stages: [{ $sort: spec }] };\n  },\n};\n\n// \u2500\u2500 .toReversed() \u2192 flips the preceding $sort spec \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Zero-arg. Only valid when the immediately preceding stage is a `$sort` \u2014\n// MongoDB streams of documents have no natural ordering, so reversing requires\n// a sort key. In the `$$ = $$.<chain>` form that preceding `$sort` comes from a\n// `.toSorted(...)` earlier in the same chain; in the bare-statement form\n// (`$$.toReversed();`) it can also come from a prior statement or a literal\n// `$sort(...)` stage, since the chain is lowered against the live pipeline.\n// Lowering doesn't emit a new $sort stage: it rewrites the preceding one with\n// all directions flipped (1 \u2192 -1, -1 \u2192 1), so the total stage count stays equal\n// to a hand-written descending `.toSorted`.\nconst TO_REVERSED: StreamMethodDef = {\n  name: \"toReversed\",\n  validate(args, callPos) {\n    if (args.length !== 0) {\n      throw new CodegenError(`.toReversed() takes no arguments, got ${args.length}.`, callPos);\n    }\n  },\n  lower(_args, _ctx, callPos, _lowerBlock, prevStages) {\n    const last = prevStages[prevStages.length - 1] as Record<string, unknown> | undefined;\n    const sortSpec = last !== undefined ? (last[\"$sort\"] as Record<string, unknown> | undefined) : undefined;\n    if (sortSpec === undefined) {\n      throw new CodegenError(\n        `.toReversed() needs a preceding $sort (from a '.toSorted(...)' call or a '$sort' stage) to invert \u2014 MongoDB streams have no natural document ordering. Either swap to '.toSorted((a, b) => b.<field> - a.<field>)' for descending directly, or place '.toReversed()' after a sort.`,\n        callPos,\n      );\n    }\n    const flipped: Record<string, 1 | -1> = {};\n    for (const key of Object.keys(sortSpec)) {\n      const dir = sortSpec[key];\n      if (dir !== 1 && dir !== -1) {\n        throw new CodegenError(\n          `.toReversed() can only invert a '$sort' with numeric 1/-1 directions (preceding stage has '${key}: ${String(dir)}'). Inverting non-direction sort specs (text-meta, custom expressions) isn't supported.`,\n          callPos,\n        );\n      }\n      flipped[key] = dir === 1 ? -1 : 1;\n    }\n    return { stages: [{ $sort: flipped }], replacesPreviousStage: true };\n  },\n};\n\n// \u2500\u2500 .flatMap(d => d.<path>) \u2192 $unwind \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// v1 only supports bare-field-path bodies. The lambda body must walk back\n// to the param ref through `.member` / `[\"literal\"]` access; the lowered\n// stage is a single `$unwind: \"$<path>\"` that splits each input doc into\n// one-per-element, with surrounding fields preserved (MQL-natural \u2014 differs\n// from JS `flatMap` which yields bare elements).\n//\n// Users who want JS-faithful \"just the elements\" can chain\n// `.map(d => d.<path>)` after to project the unwound array down to its\n// element. More complex bodies (e.g. `.flatMap(d => d.items.map(...))`)\n// would require a slot allocator threaded through the chain walker;\n// deferred to a follow-up.\n\nfunction paramFieldPath(expr: Expr, param: string): string | null {\n  const segments: string[] = [];\n  let cur: Expr = expr;\n  while (cur.type === \"MemberAccess\" || cur.type === \"IndexAccess\") {\n    if (cur.type === \"MemberAccess\") {\n      segments.unshift(cur.member);\n      cur = cur.object;\n      continue;\n    }\n    if (cur.type === \"IndexAccess\" && cur.index.type === \"StringLiteral\") {\n      segments.unshift(cur.index.value);\n      cur = cur.object;\n      continue;\n    }\n    return null;\n  }\n  if (cur.type !== \"ParamRef\") return null;\n  if (cur.name !== param) return null;\n  if (segments.length === 0) return null;\n  return segments.join(\".\");\n}\n\nconst FLAT_MAP: StreamMethodDef = {\n  name: \"flatMap\",\n  validate(args, callPos) {\n    if (args.length !== 1) {\n      throw new CodegenError(\n        `.flatMap(d => d.<path>) takes exactly one argument (a single-parameter arrow), got ${args.length}.`,\n        callPos,\n      );\n    }\n    const arg = args[0];\n    if (arg.type === \"SpreadElement\") {\n      throw new CodegenError(`.flatMap(...) does not accept a spread argument.`, arg.pos);\n    }\n    if (arg.type !== \"Lambda\") {\n      throw new CodegenError(\n        `.flatMap(d => d.<path>) requires an arrow function \u2014 in v1 the body must be a bare field-path on the lambda param (e.g. 'd.items', 'd.profile.tags').`,\n        arg.pos,\n      );\n    }\n    if (arg.params.length !== 1) {\n      throw new CodegenError(\n        `.flatMap(d => d.<path>) requires a single-parameter arrow (got ${arg.params.length} params).`,\n        arg.pos,\n      );\n    }\n    if (arg.body === undefined) {\n      throw new CodegenError(`.flatMap(d => d.<path>) requires an expression body, not a block.`, arg.pos);\n    }\n  },\n  lower(args, _ctx, callPos, _lowerBlock, _prevStages) {\n    const lambda = args[0] as LambdaNode;\n    const param = lambda.params[0];\n    const body = lambda.body as Expr;\n    const path = paramFieldPath(body, param);\n    if (path === null) {\n      throw new CodegenError(\n        `.flatMap(d => \u2026) v1 only supports a bare field-path body on the lambda param (e.g. '.flatMap(d => d.items)'). Complex bodies (e.g. '.flatMap(d => d.items.map(...))') aren't supported yet \u2014 hoist the transformation to a separate stage above the chain.`,\n        body.pos ?? callPos,\n      );\n    }\n    return { stages: [{ $unwind: `$${path}` }] };\n  },\n};\n\n// \u2500\u2500 $$ = [{ key: $$.reduce(\u2026) }] wrap pattern \u2192 $group + $replaceWith \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// `.reduce(...)` is NOT a chain method on `$$`. In JS, `arr.reduce(...)`\n// returns a single value (scalar / object / array depending on the\n// reducer); assigning a non-array value directly to `$$` would violate\n// the \"stream is always an array of docs\" invariant. So jsmql requires\n// the user to **explicitly wrap** the reduce result(s) into a stream-\n// shaped RHS:\n//\n//   - For scalar reducers: `$$ = [{ <key>: $$.reduce(<reducer>, <init>) }];`\n//     The wrap turns the scalar into a named field of a single-doc stream.\n//   - For object reducers: `$$ = [$$.reduce(<reducer>, <init>)];`\n//     (future work \u2014 needs object-returning reducer patterns).\n//\n// This file owns the scalar-into-object wrap. Each entry of the inner\n// object must be a direct `$$.reduce(...)` call; lowering pattern-matches\n// each reducer body to a MongoDB `$group` accumulator and emits:\n//\n//   [\n//     { $group: { _id: null, <key>: { $sum/$max/$min: <expr> }, ... } },\n//     { $replaceWith: { <key>: \"$<key>\", ... } },                    // drop _id\n//   ]\n//\n// Reducer-body shapes (pattern-matched per entry):\n//\n//   `acc + d.<field>`              \u2192 `{ $sum: \"$<field>\" }`\n//   `acc + 1`                       \u2192 `{ $sum: 1 }` (count documents)\n//   `Math.max(acc, d.<field>)`     \u2192 `{ $max: \"$<field>\" }`\n//   `Math.min(acc, d.<field>)`     \u2192 `{ $min: \"$<field>\" }`\n//\n// The `init` argument is required (JS-faithful \u2014 `.reduce` without an\n// initial value is a footgun in JS too) but its specific value is unused\n// in the `$group` lowering (MongoDB accumulators have their own neutral\n// elements). Validated to be a literal so a stray `$.field` reference\n// can't sneak through.\n//\n// Distinct from the existing `.reduce` chained terminal on\n// `$$$.<coll>.find/filter(...)` chains (in `lookup-translation.ts`) \u2014\n// that one builds a `$reduce` expression over a materialised array slot.\n// Different surface, different target operator, intentionally kept\n// separate. `.reduce` is also explicitly NOT in `STREAM_METHODS` \u2014 the\n// chain walker rejects it with an actionable wrap-pattern hint via\n// `unknownStreamMethod`.\n\ntype ReduceAccumulator =\n  | { kind: \"sum\"; value: string | number }\n  | { kind: \"max\"; value: string }\n  | { kind: \"min\"; value: string }\n  | { kind: \"first\"; value: string }\n  | { kind: \"last\"; value: string }\n  | { kind: \"push\"; value: string };\n\nexport type ReduceWrapEntry = { key: string; accumulator: ReduceAccumulator; pos: number };\n\n/**\n * Pattern-match an accumulator expression. The `isAccRef` predicate decides\n * what counts as the accumulator reference \u2014 for scalar reducers it's\n * `ParamRef(accParam)`; for object reducers (one accumulator per key) it's\n * `MemberAccess { object: ParamRef(accParam), member: key }`. Reusing one\n * matcher keeps the supported reducer shapes in lock-step across both forms.\n *\n * Recognised body shapes:\n *   - `<acc> + d.<path>`        \u2192  $sum: \"$<path>\"\n *   - `<acc> + 1`                \u2192  $sum: 1 (count)\n *   - `Math.max(<acc>, d.<path>)`\u2192  $max: \"$<path>\"\n *   - `Math.min(<acc>, d.<path>)`\u2192  $min: \"$<path>\"\n *   - `<acc> ?? d.<path>`        \u2192  $first: \"$<path>\" (first non-null value)\n *   - `d.<path>` (acc-ignoring)  \u2192  $last: \"$<path>\" (always-overwrite \u21D2 last value)\n *   - `[...<acc>, d.<path>]`     \u2192  $push: \"$<path>\"\n *   - `<acc>.concat(d.<path>)`   \u2192  $push: \"$<path>\" (alt spelling)\n */\nfunction classifyAccumulatorExpr(body: Expr, isAccRef: (e: Expr) => boolean, dParam: string): ReduceAccumulator | null {\n  // $sum / count via `acc + ...`\n  if (body.type === \"BinaryExpr\" && body.op === \"+\") {\n    const otherSide = isAccRef(body.left) ? body.right : isAccRef(body.right) ? body.left : null;\n    if (otherSide !== null) {\n      if (otherSide.type === \"NumberLiteral\" && otherSide.value === 1) {\n        return { kind: \"sum\", value: 1 };\n      }\n      const path = paramFieldPath(otherSide, dParam);\n      if (path !== null) return { kind: \"sum\", value: `$${path}` };\n    }\n  }\n  // $max / $min via Math.max(acc, d.<path>) / Math.min(acc, d.<path>)\n  if (body.type === \"MathCall\" && (body.method === \"max\" || body.method === \"min\") && body.args.length === 2) {\n    const [a0, a1] = body.args;\n    if (a0.type === \"SpreadElement\" || a1.type === \"SpreadElement\") return null;\n    const a0e = a0 as Expr;\n    const a1e = a1 as Expr;\n    const otherSide = isAccRef(a0e) ? a1e : isAccRef(a1e) ? a0e : null;\n    if (otherSide !== null) {\n      const path = paramFieldPath(otherSide, dParam);\n      if (path !== null) return { kind: body.method, value: path };\n    }\n  }\n  // $first via `acc ?? d.<path>` (or `acc.<key> ?? d.<path>` for object form).\n  // JS-faithful: ?? returns LHS if LHS is non-null, else RHS. Across the\n  // group, the accumulator stays at its initial value (null) until the first\n  // non-null d.<path> arrives \u2014 exactly $first semantics.\n  if (body.type === \"BinaryExpr\" && body.op === \"??\") {\n    if (isAccRef(body.left)) {\n      const path = paramFieldPath(body.right, dParam);\n      if (path !== null) return { kind: \"first\", value: path };\n    }\n  }\n  // $last via bare `d.<path>` \u2014 body doesn't reference acc at all, so every\n  // doc overwrites; the final value wins, matching $last in MongoDB.\n  {\n    const path = paramFieldPath(body, dParam);\n    if (path !== null) return { kind: \"last\", value: path };\n  }\n  // $push via `[...acc, d.<path>]` (single-element spread + push) OR\n  // `acc.concat(d.<path>)` (method form).\n  if (body.type === \"ArrayLiteral\" && body.elements.length === 2) {\n    const [first, second] = body.elements;\n    if (first.type === \"SpreadElement\" && isAccRef(first.argument) && second.type !== \"SpreadElement\") {\n      // Reject update-op array elements (AssignExpr/DeleteStmt/LetDecl); only\n      // Expr second elements are valid here.\n      if (second.type === \"AssignExpr\" || second.type === \"DeleteStmt\" || second.type === \"LetDecl\") return null;\n      const path = paramFieldPath(second, dParam);\n      if (path !== null) return { kind: \"push\", value: path };\n    }\n  }\n  if (body.type === \"MethodCall\" && body.method === \"concat\" && body.args.length === 1) {\n    if (isAccRef(body.object)) {\n      const arg = body.args[0];\n      if (arg.type !== \"SpreadElement\") {\n        const path = paramFieldPath(arg, dParam);\n        if (path !== null) return { kind: \"push\", value: path };\n      }\n    }\n  }\n  return null;\n}\n\nfunction classifyReduceBody(body: Expr, accParam: string, dParam: string): ReduceAccumulator | null {\n  return classifyAccumulatorExpr(body, (e) => e.type === \"ParamRef\" && e.name === accParam, dParam);\n}\n\ntype ObjectLiteralNode = Extract<Expr, { type: \"ObjectLiteral\" }>;\n\n/**\n * Detect the wrap patterns that consume `$$.reduce(...)` back into the\n * stream. Two forms, both lowering to the same `$group` + `$replaceWith`\n * pair via `lowerReduceWrap`:\n *\n *   1. **Scalar wrap.** `$$ = [{ <key>: $$.reduce(\u2026, <literal-init>), \u2026 }];`\n *      The inner array element is an object literal; each entry is a direct\n *      `$$.reduce(...)` call. One accumulator per entry.\n *\n *   2. **Object reducer.** `$$ = [$$.reduce((acc, d) => ({...acc, <key>: <expr>, ...}), { <key>: <init>, ... })];`\n *      The inner array element is the `$$.reduce(...)` call itself; the\n *      reducer body returns an object literal whose keys become the\n *      accumulator namespace. Each entry's value is pattern-matched the\n *      same way as the scalar form, except `acc` is referenced as\n *      `acc.<key>` (not bare `acc`).\n *\n * The array-returning reducer form (`$$ = [$$.reduce(... => acc.concat(...), [])]`)\n * is **not** handled here \u2014 its lowering is `$match` + `$replaceWith` rather\n * than `$group`-shaped, so it has its own detector / lowering pair\n * (`detectArrayReducerWrap` / `lowerArrayReducerWrap`).\n *\n * Returns `null` for non-matching shapes (the caller falls through to the\n * other RHS handlers, including the array-reducer detector). Throws for\n * matching-but-malformed shapes so the user sees a precise error instead of\n * a generic \"RHS must be \u2026\".\n */\nexport function detectReduceWrap(value: Expr): ReduceWrapEntry[] | null {\n  if (value.type !== \"ArrayLiteral\") return null;\n  if (value.elements.length !== 1) return null;\n  const el = value.elements[0];\n  if (el.type === \"ObjectLiteral\") return detectScalarReduceWrap(el);\n  if (el.type === \"MethodCall\" && el.method === \"reduce\" && el.object.type === \"CollectionRef\") {\n    // An ArrayLiteral init means the user wants the array-returning reducer\n    // form \u2014 let `detectArrayReducerWrap` handle it. (We could also throw\n    // here with a more precise message, but the fall-through keeps the two\n    // detectors decoupled: each one only commits to its shape when it sees\n    // its own init type.)\n    if (el.args.length === 2 && el.args[1].type === \"ArrayLiteral\") return null;\n    return detectObjectReducerWrap(el);\n  }\n  return null;\n}\n\nfunction detectScalarReduceWrap(docEl: ObjectLiteralNode): ReduceWrapEntry[] | null {\n  if (docEl.entries.length === 0) return null;\n  // First pass: every entry must be `<staticKey>: $$.reduce(...)`.\n  for (const entry of docEl.entries) {\n    if (entry.type !== \"KeyValueEntry\") return null;\n    if (entry.key.kind !== \"static\") return null;\n    const ev = entry.value;\n    if (ev.type !== \"MethodCall\") return null;\n    if (ev.method !== \"reduce\") return null;\n    if (ev.object.type !== \"CollectionRef\") return null;\n  }\n  // Second pass: validate and classify each reducer. (Throwing only happens\n  // here so a near-miss shape \u2014 e.g. a single-doc array literal with one\n  // non-reduce entry \u2014 falls through cleanly via the early `return null`s\n  // above.)\n  const out: ReduceWrapEntry[] = [];\n  for (const entry of docEl.entries) {\n    if (entry.type !== \"KeyValueEntry\" || entry.key.kind !== \"static\") continue;\n    const ev = entry.value as Extract<Expr, { type: \"MethodCall\" }>;\n    validateReduceCallBasics(ev);\n    ensureLiteralInit(ev);\n    const lambda = ev.args[0] as LambdaNode;\n    const [accParam, dParam] = lambda.params;\n    const body = lambda.body as Expr;\n    const accumulator = classifyReduceBody(body, accParam, dParam);\n    if (accumulator === null) {\n      throw new CodegenError(\n        `$$.reduce((${accParam}, ${dParam}) => \u2026) v1 supports only these reducer shapes: ` +\n          `'${accParam} + ${dParam}.<field>' (\u2192 $sum), '${accParam} + 1' (\u2192 $sum: 1, count), ` +\n          `'Math.max(${accParam}, ${dParam}.<field>)' (\u2192 $max), 'Math.min(${accParam}, ${dParam}.<field>)' (\u2192 $min). ` +\n          `Other shapes aren't supported yet \u2014 write the $group stage by hand.`,\n        body.pos ?? ev.pos,\n      );\n    }\n    out.push({ key: entry.key.name, accumulator, pos: entry.pos });\n  }\n  return out;\n}\n\nfunction detectObjectReducerWrap(reduceCall: Extract<Expr, { type: \"MethodCall\" }>): ReduceWrapEntry[] {\n  validateReduceCallBasics(reduceCall);\n  const lambda = reduceCall.args[0] as LambdaNode;\n  const initArg = reduceCall.args[1];\n  const [accParam, dParam] = lambda.params;\n  const body = lambda.body as Expr;\n  if (body.type !== \"ObjectLiteral\") {\n    throw new CodegenError(\n      `'$$ = [$$.reduce(...)]' requires the reducer to return an object literal \u2014 '(${accParam}, ${dParam}) => ({ ...${accParam}, <key>: <expr>, ... })'. ` +\n        `For scalar reducers, use the object-wrap form instead: '$$ = [{ <key>: $$.reduce((acc, d) => \u2026, <literal-init>) }];'.`,\n      body.pos,\n    );\n  }\n  if (initArg.type === \"SpreadElement\" || initArg.type !== \"ObjectLiteral\") {\n    throw new CodegenError(\n      `'$$ = [$$.reduce(<reducer>, <init>)]' with an object-returning reducer requires an object init that names each accumulator key \u2014 got '${initArg.type}'. Write '{ <key1>: <init1>, <key2>: <init2>, ... }' matching the keys returned by the reducer body.`,\n      (\"pos\" in initArg ? initArg.pos : reduceCall.pos) as number,\n    );\n  }\n  return classifyObjectReducer(reduceCall, body, initArg, accParam, dParam);\n}\n\nfunction classifyObjectReducer(\n  reduceCall: Extract<Expr, { type: \"MethodCall\" }>,\n  body: ObjectLiteralNode,\n  init: ObjectLiteralNode,\n  accParam: string,\n  dParam: string,\n): ReduceWrapEntry[] {\n  // Body entries: optional leading `...accParam` spread, then static-keyed entries.\n  const bodyEntries: { key: string; value: Expr; pos: number }[] = [];\n  let seenNamedEntry = false;\n  for (const entry of body.entries) {\n    if (entry.type === \"SpreadElement\") {\n      if (seenNamedEntry) {\n        throw new CodegenError(\n          `Object-reducer body's '...${accParam}' spread must be the first entry, not after named keys.`,\n          entry.pos,\n        );\n      }\n      const sp = entry.argument;\n      if (sp.type !== \"ParamRef\" || sp.name !== accParam) {\n        throw new CodegenError(\n          `Object-reducer body may only spread the accumulator parameter ('...${accParam}'). Spreads of other expressions aren't supported in v1.`,\n          entry.pos,\n        );\n      }\n      continue;\n    }\n    seenNamedEntry = true;\n    if (entry.key.kind !== \"static\") {\n      throw new CodegenError(\n        `Object-reducer body entry must have a static key. Computed keys ('[expr]: \u2026') aren't supported in v1.`,\n        entry.pos,\n      );\n    }\n    bodyEntries.push({ key: entry.key.name, value: entry.value, pos: entry.pos });\n  }\n  if (bodyEntries.length === 0) {\n    throw new CodegenError(\n      `Object-reducer body must declare at least one '<key>: <reducer-expr>' entry (got an empty or spread-only object).`,\n      body.pos,\n    );\n  }\n  // Init keys.\n  const initKeys = new Set<string>();\n  for (const entry of init.entries) {\n    if (entry.type !== \"KeyValueEntry\") {\n      throw new CodegenError(\n        `The init object passed to $$.reduce must be a literal '{ <key>: <init>, ... }' \u2014 spreads aren't supported in v1.`,\n        entry.pos,\n      );\n    }\n    if (entry.key.kind !== \"static\") {\n      throw new CodegenError(`The init object's keys must be static (no computed '[expr]:' keys).`, entry.pos);\n    }\n    initKeys.add(entry.key.name);\n  }\n  // Body keys must match init keys exactly. (Asymmetric sets would mean\n  // either an accumulator with no starting value or a starting value with\n  // no per-doc update \u2014 both are user-side bugs in JS too.)\n  const bodyKeys = new Set(bodyEntries.map((e) => e.key));\n  const missingInInit = Array.from(bodyKeys).filter((k) => !initKeys.has(k));\n  const missingInBody = Array.from(initKeys).filter((k) => !bodyKeys.has(k));\n  if (missingInInit.length > 0 || missingInBody.length > 0) {\n    const parts: string[] = [];\n    if (missingInInit.length > 0) parts.push(`init is missing keys [${missingInInit.join(\", \")}]`);\n    if (missingInBody.length > 0) parts.push(`body is missing keys [${missingInBody.join(\", \")}]`);\n    throw new CodegenError(\n      `Object-reducer body and init must declare the same keys (${parts.join(\"; \")}). Each key needs a starting value in init and a per-doc update in the body.`,\n      reduceCall.pos,\n    );\n  }\n  // Classify each body entry's value.\n  const out: ReduceWrapEntry[] = [];\n  for (const entry of bodyEntries) {\n    const accumulator = classifyAccumulatorExpr(\n      entry.value,\n      (e) =>\n        e.type === \"MemberAccess\" &&\n        e.object.type === \"ParamRef\" &&\n        e.object.name === accParam &&\n        e.member === entry.key,\n      dParam,\n    );\n    if (accumulator === null) {\n      throw new CodegenError(\n        `Object-reducer entry '${entry.key}: \u2026' \u2014 v1 supports only: ` +\n          `'${accParam}.${entry.key} + ${dParam}.<field>' (\u2192 $sum), '${accParam}.${entry.key} + 1' (\u2192 $sum: 1, count), ` +\n          `'Math.max(${accParam}.${entry.key}, ${dParam}.<field>)' (\u2192 $max), 'Math.min(${accParam}.${entry.key}, ${dParam}.<field>)' (\u2192 $min). ` +\n          `Each entry must reference '${accParam}.${entry.key}' as the accumulator side.`,\n        entry.value.pos ?? entry.pos,\n      );\n    }\n    out.push({ key: entry.key, accumulator, pos: entry.pos });\n  }\n  return out;\n}\n\nfunction validateReduceCallBasics(call: Extract<Expr, { type: \"MethodCall\" }>): void {\n  if (call.args.length !== 2) {\n    throw new CodegenError(\n      `$$.reduce((acc, d) => <expr>, <init>) takes exactly two arguments (the reducer arrow and the initial value), got ${call.args.length}.`,\n      call.pos,\n    );\n  }\n  const [arg0, arg1] = call.args;\n  if (arg0.type === \"SpreadElement\") {\n    throw new CodegenError(`$$.reduce(...) does not accept spread arguments.`, arg0.pos);\n  }\n  if (arg1.type === \"SpreadElement\") {\n    throw new CodegenError(`$$.reduce(...) does not accept spread arguments.`, arg1.pos);\n  }\n  if (arg0.type !== \"Lambda\") {\n    throw new CodegenError(\n      `$$.reduce((acc, d) => <expr>, <init>) requires an arrow function as the first argument.`,\n      arg0.pos,\n    );\n  }\n  if (arg0.params.length !== 2) {\n    throw new CodegenError(\n      `$$.reduce((acc, d) => <expr>, <init>) requires a two-parameter arrow '(acc, d) => \u2026' (got ${arg0.params.length} params).`,\n      arg0.pos,\n    );\n  }\n  if (arg0.body === undefined) {\n    throw new CodegenError(`$$.reduce(...) requires an expression body, not a block.`, arg0.pos);\n  }\n}\n\nfunction ensureLiteralInit(call: Extract<Expr, { type: \"MethodCall\" }>): void {\n  const arg1 = call.args[1] as Expr;\n  const isLiteral =\n    arg1.type === \"NumberLiteral\" ||\n    arg1.type === \"StringLiteral\" ||\n    arg1.type === \"BooleanLiteral\" ||\n    arg1.type === \"NullLiteral\" ||\n    arg1.type === \"BigIntLiteral\";\n  if (!isLiteral) {\n    throw new CodegenError(\n      `$$.reduce((acc, d) => <scalar-expr>, <init>) \u2014 the initial value must be a literal (number, string, boolean, null) for the scalar wrap form. For object-returning reducers, use '$$ = [$$.reduce((acc, d) => ({ ...acc, ... }), { ... })];' instead.`,\n      (\"pos\" in arg1 ? arg1.pos : call.pos) as number,\n    );\n  }\n}\n\n// \u2500\u2500 Dictionary-build reducer wrap \u2192 $group + $replaceWith \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// `$$ = [$$.reduce((acc, d) => ({ ...acc, [d.<keyPath>]: <d.<valPath>|d> }), {})];`\n//\n// The single-computed-key form of the object-returning reducer. Distinct from\n// the static-key object-reducer (which the user names every accumulator at\n// compile time) because here the *keys come from runtime data* \u2014 one input\n// doc, one output entry, key/value both read off the doc. Lowers to:\n//\n//   [{ $group:       { _id: null, __jsmqlDict: { $push: { k: \"$<keyPath>\", v: \"$<valPath>\"|\"$$ROOT\" } } } },\n//    { $replaceWith: { $arrayToObject: \"$__jsmqlDict\" } }]\n//\n// The leading `...acc` spread is supported (JS-faithful \u2014 that's how `{ ...acc, [k]: v }`\n// is conventionally spelled in JS) but optional: `(acc, d) => ({ [d.k]: d.v })`\n// works equally well. The init MUST be `{}` (empty object) \u2014 non-empty seeds\n// have no MQL accumulator analogue. Mixed shapes (computed key + static key in\n// the same body, e.g. `({ ...acc, [d.k]: d.v, count: acc.count + 1 })`) fall\n// through to the existing object-reducer path, which will report the\n// computed-key error there.\n\nexport type DictBuildWrap = {\n  /** Path on `d` for the dict-entry key (e.g. \"id\" or \"user.email\"). */\n  keyPath: string;\n  /** Path on `d` for the dict-entry value, OR null when the value is the bare doc. */\n  valuePath: string | null;\n  /** Lambda position for actionable errors. */\n  lambdaPos: number;\n};\n\n/**\n * Detect the dict-build wrap form. Returns null if the shape doesn't match\n * (so `detectReduceWrap` / `detectArrayReducerWrap` can have a turn);\n * returns a `DictBuildWrap` when it does match cleanly.\n *\n * Deliberately narrow: requires exactly one computed-key entry (plus optional\n * leading `...acc` spread), key path rooted on the `d` param, value path or\n * bare `d`, and `{}` init. Anything richer (multiple computed keys, mixed\n * static + computed, computed key reading from `acc`) is not this pattern\n * and either lands in the existing object-reducer path or surfaces a clear\n * error there.\n */\nexport function detectDictBuildWrap(value: Expr): DictBuildWrap | null {\n  if (value.type !== \"ArrayLiteral\") return null;\n  if (value.elements.length !== 1) return null;\n  const el = value.elements[0];\n  if (el.type !== \"MethodCall\" || el.method !== \"reduce\" || el.object.type !== \"CollectionRef\") return null;\n  if (el.args.length !== 2) return null;\n  const lambda = el.args[0];\n  const init = el.args[1];\n  if (lambda.type === \"SpreadElement\" || init.type === \"SpreadElement\") return null;\n  if (lambda.type !== \"Lambda\" || lambda.params.length !== 2 || lambda.body === undefined) return null;\n  if (init.type !== \"ObjectLiteral\" || init.entries.length !== 0) return null;\n  const body = lambda.body;\n  if (body.type !== \"ObjectLiteral\") return null;\n  const [accParam, dParam] = lambda.params;\n  // Walk entries: optional leading `...acc` spread, then exactly one\n  // computed-key entry. Any other shape (static keys, second computed entry,\n  // bare-value spreads) is not dict-build.\n  let seenComputed = false;\n  let result: DictBuildWrap | null = null;\n  for (const entry of body.entries) {\n    if (entry.type === \"SpreadElement\") {\n      if (seenComputed) return null;\n      if (entry.argument.type !== \"ParamRef\" || entry.argument.name !== accParam) return null;\n      continue;\n    }\n    // KeyValueEntry\n    if (seenComputed) return null;\n    if (entry.key.kind !== \"computed\") return null;\n    const keyPath = paramFieldPath(entry.key.expr, dParam);\n    if (keyPath === null) return null;\n    const valuePath = paramFieldOrBareParam(entry.value, dParam);\n    if (valuePath === undefined) return null;\n    result = { keyPath, valuePath, lambdaPos: lambda.pos };\n    seenComputed = true;\n  }\n  return result;\n}\n\n/**\n * Bare `d` \u2192 null (lowering uses `$$ROOT`); `d.<path>` \u2192 \"<path>\".\n * Anything else returns `undefined` (caller bails to \"not dict-build\").\n */\nfunction paramFieldOrBareParam(expr: Expr, param: string): string | null | undefined {\n  if (expr.type === \"ParamRef\" && expr.name === param) return null;\n  const path = paramFieldPath(expr, param);\n  if (path !== null) return path;\n  return undefined;\n}\n\n/**\n * Lower a detected dict-build wrap to the `$group` + `$replaceWith` pair.\n * One internal-namespace slot (`__jsmqlDict`) collects the `{k, v}` pairs;\n * `$arrayToObject` folds the pair-array into the final dict.\n */\nexport function lowerDictBuildWrap(wrap: DictBuildWrap): object[] {\n  const v: string = wrap.valuePath === null ? \"$$ROOT\" : `$${wrap.valuePath}`;\n  return [\n    { $group: { _id: null, __jsmqlDict: { $push: { k: `$${wrap.keyPath}`, v } } } },\n    { $replaceWith: { $arrayToObject: \"$__jsmqlDict\" } },\n  ];\n}\n\n/**\n * Emit the `$group` + `$replaceWith` pair for a detected `[{key: $$.reduce(\u2026), \u2026}]`\n * wrap. The `$group` collects every keyed accumulator under `_id: null`; the\n * trailing `$replaceWith` drops the `_id: null` field so the output stream is\n * a single doc with exactly the user-named keys.\n */\nexport function lowerReduceWrap(entries: readonly ReduceWrapEntry[]): object[] {\n  const groupBody: Record<string, unknown> = { _id: null };\n  const replaceBody: Record<string, unknown> = {};\n  for (const entry of entries) {\n    const acc = entry.accumulator;\n    // Map accumulator kind to MQL operator and value form. `sum` is the only\n    // kind that takes a non-`$<path>` value (`1` for the count form); every\n    // other kind takes a `$<path>` field reference.\n    const op =\n      acc.kind === \"sum\"\n        ? \"$sum\"\n        : acc.kind === \"max\"\n          ? \"$max\"\n          : acc.kind === \"min\"\n            ? \"$min\"\n            : acc.kind === \"first\"\n              ? \"$first\"\n              : acc.kind === \"last\"\n                ? \"$last\"\n                : \"$push\";\n    const v: string | number = acc.kind === \"sum\" ? acc.value : `$${acc.value}`;\n    groupBody[entry.key] = { [op]: v };\n    replaceBody[entry.key] = `$${entry.key}`;\n  }\n  return [{ $group: groupBody }, { $replaceWith: replaceBody }];\n}\n\n// \u2500\u2500 Array-returning reducer wrap \u2192 $match (optional) + $replaceWith \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// `$$ = [$$.reduce(<reducer>, [])];` \u2014 the third wrap form. Used when the\n// reducer collapses the stream into a flat array of projected docs:\n//\n//   \u2022 Unconditional map:  '(acc, d) => acc.concat(d.<path>)'\n//       \u2192 '[{$replaceWith: \"$<path>\"}]'   (each input doc becomes its sub-doc)\n//\n//   \u2022 Filter + map (ternary):  '(acc, d) => (cond ? acc.concat(d.<path>) : acc)'\n//       \u2192 '[{$match: <cond translated>}, {$replaceWith: \"$<path>\"}]'\n//\n//   \u2022 Identity variants where `d` itself is concatted (bare param, no `.path`)\n//     skip the `$replaceWith` \u2014 the docs flow through unchanged.\n//\n// The init MUST be `[]` (empty array) \u2014 non-empty initial arrays are rejected\n// because no MQL accumulator preserves a JS-faithful \"seed array\" semantic.\n// The body's `.concat(...)` argument must be a path on `d` (a sub-doc the\n// stream will replace each input doc with) or bare `d` (identity, used for\n// pure filter shapes).\n//\n// Distinct from the `$group`-shaped scalar/object wraps because the output\n// is a doc-shaped stream of the projected fields, not a single summary doc.\n// Detection commits at the init-is-empty-ArrayLiteral check; lowering lives\n// in `pipeline.ts` so it can reuse `lowerStreamFilterPredicate` for the\n// condition (same predicate translation `.filter` uses).\n\nexport type ArrayReducerProject = { kind: \"field\"; path: string } | { kind: \"identity\" };\n\nexport type ArrayReducerWrap = {\n  /** Identity (`acc.concat(d)`) or field-path projection (`acc.concat(d.<path>)`). */\n  project: ArrayReducerProject;\n  /**\n   * When present, the lowering emits a `$match` stage before the projection\n   * using this expression as the predicate body. Translated through\n   * `lowerStreamFilterPredicate` in pipeline.ts (same engine `.filter` uses).\n   */\n  condition: Expr | null;\n  /** The reducer's per-doc parameter name (used to translate the condition). */\n  dParam: string;\n  /** Lambda position (for actionable errors). */\n  lambdaPos: number;\n};\n\n/** `$$.reduce(<reducer>, [<...>])` \u2014 a reduce on the stream seeded with an array literal. */\nfunction isArrayInitReduce(el: ArrayElement): el is Extract<Expr, { type: \"MethodCall\" }> {\n  return (\n    el.type === \"MethodCall\" &&\n    el.method === \"reduce\" &&\n    el.object.type === \"CollectionRef\" &&\n    el.args.length === 2 &&\n    el.args[1].type === \"ArrayLiteral\"\n  );\n}\n\n/**\n * Detect `$$ = $$.reduce(<reducer>, [])` \u2014 the array-returning reducer form.\n * A reducer seeded with `[]` already returns an array, i.e. a stream, so it is\n * assigned **unbracketed**. Returns the classified `ArrayReducerWrap`, or null\n * for non-matching shapes (the caller falls through to other handlers).\n *\n * Throws for: the legacy **bracketed** form `$$ = [$$.reduce(\u2026, [])]` (wrapping\n * a stream in `[ ]` yields `[[\u2026]]` \u2014 nonsense; the throw points at the\n * unbracketed form); a non-empty seed array; and unrecognised reducer bodies.\n */\nexport function detectArrayReducerWrap(value: Expr): ArrayReducerWrap | null {\n  // Legacy bracketed shape: detect it precisely and reject with a fix-it hint.\n  // Everything else inside an array literal falls through to `null`.\n  if (value.type === \"ArrayLiteral\") {\n    if (value.elements.length !== 1) return null;\n    if (!isArrayInitReduce(value.elements[0])) return null;\n    throw new CodegenError(\n      `A reducer seeded with '[]' already produces a stream, so don't wrap it in '[ ]' \u2014 assign it directly: '$$ = $$.reduce((acc, d) => \u2026, [])'.`,\n      value.pos,\n    );\n  }\n  if (!isArrayInitReduce(value)) return null;\n  const el = value;\n  const initArg = el.args[1];\n  // Past this point we commit \u2014 throw for malformed shapes.\n  if (initArg.type === \"ArrayLiteral\" && initArg.elements.length !== 0) {\n    throw new CodegenError(\n      `'$$ = $$.reduce(<reducer>, <init>)' with an array-returning reducer requires the init to be '[]' \u2014 a non-empty seed array isn't supported (no MQL accumulator preserves the JS-faithful \"start with these elements\" semantic).`,\n      initArg.pos,\n    );\n  }\n  validateReduceCallBasics(el);\n  const lambda = el.args[0] as LambdaNode;\n  const [accParam, dParam] = lambda.params;\n  const body = lambda.body as Expr;\n  const classified = classifyArrayReducerBody(body, accParam, dParam);\n  if (classified === null) {\n    throw new CodegenError(\n      `Array-returning reducer body \u2014 v1 supports only:\\n` +\n        `  \u2022 Unconditional map:  '(${accParam}, ${dParam}) => ${accParam}.concat(${dParam}.<field>)'  \u2192  '$replaceWith: \"$<field>\"'\\n` +\n        `  \u2022 Filter + map:       '(${accParam}, ${dParam}) => (<cond> ? ${accParam}.concat(${dParam}.<field>) : ${accParam})'  \u2192  '$match(<cond>) + $replaceWith: \"$<field>\"'\\n` +\n        `  \u2022 The '${dParam}' itself (bare param) instead of '${dParam}.<field>' projects the whole doc (no '$replaceWith').\\n` +\n        `Other shapes \u2014 '${accParam}.concat([${dParam}.<x>, ${dParam}.<y>])', '[...${accParam}, ${dParam}.<x>]', non-ternary branches \u2014 aren't supported yet.`,\n      body.pos,\n    );\n  }\n  return { ...classified, dParam, lambdaPos: lambda.pos };\n}\n\nfunction classifyArrayReducerBody(\n  body: Expr,\n  accParam: string,\n  dParam: string,\n): { project: ArrayReducerProject; condition: Expr | null } | null {\n  // Filter + map: `<cond> ? <concat-call> : acc`\n  if (body.type === \"TernaryExpr\") {\n    if (body.alternate.type !== \"ParamRef\" || body.alternate.name !== accParam) return null;\n    const project = classifyConcatCall(body.consequent, accParam, dParam);\n    if (project === null) return null;\n    return { project, condition: body.condition };\n  }\n  // Unconditional map: `<concat-call>`\n  const project = classifyConcatCall(body, accParam, dParam);\n  if (project !== null) return { project, condition: null };\n  return null;\n}\n\nfunction classifyConcatCall(expr: Expr, accParam: string, dParam: string): ArrayReducerProject | null {\n  if (expr.type !== \"MethodCall\") return null;\n  if (expr.method !== \"concat\") return null;\n  if (expr.object.type !== \"ParamRef\" || expr.object.name !== accParam) return null;\n  if (expr.args.length !== 1) return null;\n  const arg = expr.args[0];\n  if (arg.type === \"SpreadElement\") return null;\n  // Bare `d` \u2014 identity (no projection).\n  if (arg.type === \"ParamRef\" && arg.name === dParam) return { kind: \"identity\" };\n  // `d.<path>` \u2014 field-path projection.\n  const path = paramFieldPath(arg, dParam);\n  if (path !== null) return { kind: \"field\", path };\n  return null;\n}\n\n// \u2500\u2500 Registry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst STREAM_METHODS: Record<string, StreamMethodDef> = {\n  slice: SLICE,\n  concat: CONCAT,\n  map: MAP,\n  toSorted: TO_SORTED,\n  toReversed: TO_REVERSED,\n  flatMap: FLAT_MAP,\n  // Note: `.reduce` is deliberately NOT in this registry. `arr.reduce(...)`\n  // returns a scalar / object / array in JS depending on the reducer. A\n  // scalar/object result must be wrapped into a stream-shaped RHS; an\n  // array-returning reducer already IS a stream and is assigned unbracketed.\n  // The chain walker's `unknownStreamMethod` helper special-cases `.reduce`\n  // with an actionable hint, and the forms are implemented above:\n  //   \u2022 `detectReduceWrap`         \u2014 scalar-into-object `$$ = [{ k: $$.reduce(\u2026) }]` & object-returning `$$ = [$$.reduce(\u2026, {})]` ($group + $replaceWith)\n  //   \u2022 `detectArrayReducerWrap`   \u2014 array-returning `$$ = $$.reduce(\u2026, [])`, unbracketed ($match + $replaceWith); the bracketed form throws\n};\n\n/** Look up a registered stream method by name; null if not registered. */\nexport function lookupStreamMethod(name: string): StreamMethodDef | null {\n  return STREAM_METHODS[name] ?? null;\n}\n\n/** Names of all registered stream methods (for error messages). */\nexport function streamMethodNames(): readonly string[] {\n  return Object.keys(STREAM_METHODS);\n}\n\n// \u2500\u2500 Chain collection helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type MethodCallNode = Extract<Expr, { type: \"MethodCall\" }>;\n\nexport type StreamChain = {\n  /** The receiver at the innermost end of the chain (CollectionRef, DatabaseRef-rooted member access, etc.). */\n  root: Expr;\n  /** Method calls in the order they apply (innermost first). */\n  methods: MethodCallNode[];\n};\n\n/**\n * Walk an Expr that's expected to be a chain of `.method(...)` calls and\n * separate the innermost receiver from the chain. Always succeeds \u2014\n * non-MethodCall input returns `{ root: expr, methods: [] }`. Callers\n * inspect `root.type` to decide whether the chain is rooted at a\n * legitimate stream/collection receiver.\n */\nexport function collectStreamChain(expr: Expr): StreamChain {\n  const methods: MethodCallNode[] = [];\n  let cur: Expr = expr;\n  while (cur.type === \"MethodCall\") {\n    methods.push(cur);\n    cur = cur.object;\n  }\n  methods.reverse();\n  return { root: cur, methods };\n}\n", "// Cross-collection lookup translation: lowers `$$$.<coll>.find/filter(pred)`\n// and its chained-read forms into MongoDB `$lookup` (+ follow-up) stages.\n//\n// Three responsibilities:\n//\n//   1. **Detect** a lookup call in an arbitrary expression position\n//      (`detectLookupCall`).\n//\n//   2. **Translate** the predicate lambda into either the basic-form\n//      shape (`{ from, localField, foreignField, as }`) when the body\n//      collapses to a single `===` between a foreign path and a `$.`\n//      local path, or the correlated-pipeline shape\n//      (`{ from, let, pipeline: [...], as }`) otherwise. The pipeline\n//      form auto-hoists every `$.x` reference into a `let` entry whose\n//      name is the path's last segment; references to the foreign-doc\n//      lambda param (`o.x.y`) are rewritten to bare `FieldRef` so they\n//      lower to `\"$x.y\"` inside the sub-pipeline (foreign doc is\n//      `$$ROOT` there). Block-body lambdas (`o => { stmt; stmt; }`)\n//      always go through the pipeline form, using the block stmts as\n//      the sub-pipeline body verbatim.\n//\n//   3. **Materialise** the lookup result into a pipeline stage,\n//      writing to either a user-named slot (when the lookup is the\n//      whole RHS of an assignment or `let`) or an internal\n//      `__jsmql.__lookup<N>` slot. For `.find`, an extra\n//      `$set { <slot>: { $first: \"$<slot>\" } }` stage follows the\n//      `$lookup` so the slot holds scalar-or-null instead of an array\n//      \u2014 JS-faithful semantics. For chained terminals (`.length`,\n//      `.reduce(fn, init)`), a third `$set` stage applies the\n//      reduction over the slot. Internal slots ride the existing\n//      `__jsmql` cleanup at the end of the pipeline \u2014 no per-temp\n//      `$unset` emitted.\n//\n// `containsLookupCall` is the cheap walk used by `index.ts` to\n// pre-reject lookup syntax in Filter / `jsmql.expr` / `jsmql.update`\n// modes before codegen, so the user sees an actionable \"use Pipeline\n// mode\" error instead of the generic `DatabaseRef` reserved-syntax\n// throw.\n//\n// See `docs/specs/lookup-stage.md` for the full design, the predicate-\n// translation algorithm, and the error catalog.\n\nimport type {\n  Expr,\n  Pipeline,\n  PipelineStmt,\n  UpdateFilter,\n  UpdateOp,\n  CallArg,\n  ArrayElement,\n  ObjectEntry,\n  KeyValueEntry,\n} from \"./ast.ts\";\nimport { CodegenError, EMPTY_CTX, generateWithCtx, freshSubPipelineCtx, type GenerateCtx } from \"./codegen.ts\";\nimport { translateMatchBody, mergeTranslatedQuery, type MatchTranslation } from \"./match-translation.ts\";\nimport { didYouMean } from \"./levenshtein.ts\";\n// Cycle-safe import: stream-methods.ts imports SlotAllocator / SubPipelineLowerer\n// from this module, and lookupStreamMethod is a runtime function (not consumed\n// at this module's top level), so ESM's late-binding handles it cleanly.\nimport { lookupStreamMethod } from \"./stream-methods.ts\";\n\n// AST shapes are exported only as the discriminated union `Expr`. The\n// specific variants we touch directly need local aliases extracted from\n// that union \u2014 saves us from re-declaring the shapes and keeps the\n// types in lock-step with `src/ast.ts`.\ntype Lambda = Extract<Expr, { type: \"Lambda\" }>;\ntype FieldRef = Extract<Expr, { type: \"FieldRef\" }>;\ntype ParamRef = Extract<Expr, { type: \"ParamRef\" }>;\ntype MethodCall = Extract<Expr, { type: \"MethodCall\" }>;\n\n/**\n * Caller-supplied sub-pipeline lowerer. lookup-translation lives \"below\"\n * pipeline.ts in the dependency graph (pipeline.ts imports from here),\n * so a direct import back into pipeline.ts would be circular. The\n * top-level orchestrator in pipeline.ts wires this through when it\n * invokes `lowerLookup` / `extractLookupCalls`.\n */\nexport type SubPipelineLowerer = (block: Pipeline, ctx: GenerateCtx) => object[];\n\n/**\n * State carried into a lookup translation when it's *nested* inside another\n * lookup's predicate. Empty at the top level; populated as we recurse.\n *\n * - `foreignParams` \u2014 every enclosing lookup's lambda param name, outermost\n *   first. References to these (e.g. `o.x`, `o.user._id`) need to lower as\n *   paths on the local doc of the enclosing pipeline, so we pre-rewrite them\n *   to `FieldRef(<path>)` before the inner's let-extractor runs. The\n *   extractor then auto-lets them into the inner's `$lookup.let` clause\n *   exactly like ordinary `$.x` refs.\n * - `inScopeLetNames` \u2014 let-var names already visible via the enclosing\n *   `$lookup.let` clauses. MQL `$$<name>` is lexically scoped through nested\n *   `$lookup.pipeline` boundaries, so the inner shouldn't re-let them. We\n *   thread the names into the inner's `lambdaParams` so codegen emits\n *   `$$<name>` instead of throwing `UnknownIdentifier`.\n */\nexport type EnclosingLookupContext = { foreignParams: ReadonlyArray<string>; inScopeLetNames: ReadonlySet<string> };\n\nexport const EMPTY_ENCLOSING: EnclosingLookupContext = { foreignParams: [], inScopeLetNames: new Set() };\n\n/**\n * Pre-rewrite `<enclosingForeignParam>.<x>.<y>...` chains to `FieldRef(\"<x>.<y>...\")`.\n *\n * In the current implementation, this helper is defensive: the outer's\n * `extractLetsFromExpr` walk already descends through nested lookup-call\n * lambda bodies (via `mapChildren`'s MethodCall case) using the outer's\n * foreignParam, so most enclosing-foreign-param refs are already rewritten\n * by the time the nested lookup's `translatePredicate` runs. The\n * defensive re-run handles only the cases where a deeper level needs to\n * rewrite refs that this level couldn't see \u2014 e.g. a fresh\n * `buildPipelineFormPredicate` invocation that wasn't preceded by an\n * outer-level extraction.\n */\nfunction rewriteEnclosingForeignParams(expr: Expr, params: ReadonlyArray<string>): Expr {\n  if (params.length === 0) return expr;\n  const paramSet = new Set(params);\n  function walk(node: Expr): Expr {\n    const path = matchEnclosingParamPath(node, paramSet);\n    if (path !== null) {\n      if (path.segments.length === 0) {\n        // Defense-in-depth: this branch is rarely reached because the outer\n        // let-extractor's classifyPath catches bare enclosing-foreign refs\n        // first (using its own foreignParam matching). Same restriction\n        // family as the \u00A7B \"Bare lambda parameter 'o' in a $lookup\n        // predicate\" rejection \u2014 no $$ROOT lowering for the foreign doc.\n        throw new CodegenError(\n          `Bare lambda parameter '${path.param}' from an enclosing lookup is not yet supported \u2014 use \\`${path.param}.<field>\\` to reference a field of the enclosing foreign document.`,\n          node.pos,\n        );\n      }\n      return { type: \"FieldRef\", path: path.segments.join(\".\"), pos: node.pos };\n    }\n    return walkChildren(node);\n  }\n  function walkChildren(node: Expr): Expr {\n    switch (node.type) {\n      case \"BinaryExpr\":\n        return { ...node, left: walk(node.left), right: walk(node.right) };\n      case \"UnaryExpr\":\n        return { ...node, operand: walk(node.operand) };\n      case \"TernaryExpr\":\n        return {\n          ...node,\n          condition: walk(node.condition),\n          consequent: walk(node.consequent),\n          alternate: walk(node.alternate),\n        };\n      case \"MemberAccess\":\n        return { ...node, object: walk(node.object) };\n      case \"IndexAccess\":\n        return { ...node, object: walk(node.object), index: walk(node.index) };\n      case \"MethodCall\":\n        return { ...node, object: walk(node.object), args: node.args.map(walkArg) };\n      case \"CallExpression\":\n        return { ...node, callee: walk(node.callee), args: node.args.map(walkArg) };\n      case \"OperatorCall\":\n        return { ...node, args: node.args.map(walkArg) };\n      case \"Lambda\":\n        if (node.body !== undefined) return { ...node, body: walk(node.body) };\n        return node;\n      case \"ArrayLiteral\":\n        return {\n          ...node,\n          elements: node.elements.map((el): ArrayElement => {\n            if (el.type === \"SpreadElement\") return { ...el, argument: walk(el.argument) };\n            if (el.type === \"AssignExpr\") return { ...el, target: walk(el.target), value: walk(el.value) };\n            if (el.type === \"DeleteStmt\") return { ...el, target: walk(el.target) };\n            if (el.type === \"LetDecl\") return { ...el, value: walk(el.value) };\n            return walk(el as Expr);\n          }),\n        };\n      case \"ObjectLiteral\":\n        return {\n          ...node,\n          entries: node.entries.map((entry): ObjectEntry => {\n            if (entry.type === \"SpreadElement\") return { ...entry, argument: walk(entry.argument) };\n            return {\n              ...entry,\n              key: entry.key.kind === \"computed\" ? { kind: \"computed\", expr: walk(entry.key.expr) } : entry.key,\n              value: walk(entry.value),\n            };\n          }),\n        };\n      case \"TemplateLiteral\":\n        return { ...node, expressions: node.expressions.map(walk) };\n      case \"TypeofExpr\":\n        return { ...node, operand: walk(node.operand) };\n      case \"NewDate\":\n        return { ...node, args: node.args.map(walk) };\n      case \"NewSet\":\n        return { ...node, arg: node.arg !== null ? walk(node.arg) : null };\n      case \"TypeCast\":\n        return { ...node, arg: walk(node.arg) };\n      case \"MathCall\":\n        return { ...node, args: node.args.map(walkArg) };\n      case \"ObjectCall\":\n        return { ...node, args: node.args.map(walkArg) };\n      case \"ArrayFrom\":\n        return { ...node, input: walk(node.input), mapFn: node.mapFn !== null ? walk(node.mapFn) : null };\n      case \"NumberStatic\":\n        return { ...node, arg: walk(node.arg) };\n      case \"DateUTC\":\n        return { ...node, args: node.args.map(walk) };\n      default:\n        return node;\n    }\n  }\n  function walkArg(arg: CallArg): CallArg {\n    if (arg.type === \"SpreadElement\") return { ...arg, argument: walk(arg.argument) };\n    return walk(arg);\n  }\n  return walk(expr);\n}\n\nfunction matchEnclosingParamPath(\n  node: Expr,\n  params: ReadonlySet<string>,\n): { param: string; segments: string[] } | null {\n  if (node.type === \"ParamRef\" && params.has(node.name)) {\n    return { param: node.name, segments: [] };\n  }\n  if (node.type === \"MemberAccess\") {\n    const inner = matchEnclosingParamPath(node.object, params);\n    if (inner !== null) return { param: inner.param, segments: [...inner.segments, node.member] };\n  }\n  if (node.type === \"IndexAccess\" && node.index.type === \"StringLiteral\") {\n    const inner = matchEnclosingParamPath(node.object, params);\n    if (inner !== null) return { param: inner.param, segments: [...inner.segments, node.index.value] };\n  }\n  return null;\n}\n\n// \u2500\u2500 Detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type LookupCall = {\n  /** Position of the context-ref prefix `$$$` / `$$$$` (for errors). */\n  pos: number;\n  /** Position of the method call (for errors specific to the call shape). */\n  callPos: number;\n  /**\n   * Database name extracted from `$$$$.<db>.<coll>` (any bracket combination).\n   * Undefined for the same-database form `$$$.<coll>` \u2014 in which case\n   * `$lookup.from` is emitted as a bare collection-name string. When set,\n   * `$lookup.from` is emitted as `{ db, coll }` \u2014 the Atlas Data Federation\n   * shape for cross-database joins. See docs/specs/lookup-stage.md.\n   */\n  db?: string;\n  /** Collection name extracted from `.<name>` or `[\"<name>\"]`. */\n  collection: string;\n  /** `.find` returns scalar-or-null; `.filter` returns an array. */\n  method: \"find\" | \"filter\";\n  /** The predicate lambda. May be expression-body OR block-body. */\n  lambda: Lambda;\n};\n\n/** One step of static (dot, string-bracket, or bound-param-bracket) member access on a receiver. */\ntype StaticAccess = { name: string; object: Expr };\n\n/**\n * Resolve one step of a lookup-receiver chain to a compile-time string name.\n * Three index kinds resolve to a static name:\n *\n *   - `MemberAccess`        (`$$$.coll`)            \u2192 the dotted member name.\n *   - `IndexAccess` whose index is a `StringLiteral` (`$$$[\"coll\"]`) \u2192 the literal.\n *   - `IndexAccess` whose index is a `ParamRef` whose name is bound in\n *     `ctx.bindings` to a string value (`jsmql.compile(({ coll }, $) => $$$[coll]\u2026)`)\n *     \u2192 the bound string.\n *\n * The third form is the new compile-time-binding case: `jsmql.compile`\n * parameter bindings are compile-time constants validated as JSON-shaped\n * values at call time, so resolving them here matches the rule MongoDB\n * itself enforces on `$lookup.from` (a plan-time constant string).\n *\n * Non-string bound values (a number, an array, etc.) throw a precise\n * \"parameter binding must be a string\" error \u2014 the dynamic-name footgun\n * surfaces at compile time instead of producing wrong MQL.\n *\n * An unbound `ParamRef` (the name isn't in `ctx.bindings` at all) returns\n * null; the downstream codegen then surfaces either the bare-reference\n * error (when the chain is reachable as a lookup) or `UnknownIdentifierError`\n * (when the ParamRef leaks into a non-lookup expression position).\n */\nfunction staticAccess(node: Expr, ctx: GenerateCtx): StaticAccess | null {\n  if (node.type === \"MemberAccess\") return { name: node.member, object: node.object };\n  if (node.type === \"IndexAccess\") {\n    if (node.index.type === \"StringLiteral\") {\n      return { name: node.index.value, object: node.object };\n    }\n    if (node.index.type === \"ParamRef\") {\n      const bindings = ctx.bindings;\n      if (bindings === undefined || !bindings.has(node.index.name)) return null;\n      const bound = bindings.get(node.index.name);\n      if (typeof bound !== \"string\") {\n        throw new CodegenError(\n          `'$$$[${node.index.name}]' / '$$$$[${node.index.name}]' parameter binding must be a string ` +\n            `(got ${typeof bound}); collection / database names are compile-time constants in MongoDB's $lookup.from.`,\n          node.index.pos,\n        );\n      }\n      return { name: bound, object: node.object };\n    }\n  }\n  return null;\n}\n\n/** Extracted target of a lookup-shaped receiver: `$$$.<coll>` or `$$$$.<db>.<coll>`. */\nexport type LookupTarget = { pos: number; db?: string; collection: string };\n\n/**\n * Walk back through one or two levels of static (dot or string-bracket) access\n * to recognise the four lookup-receiver shapes:\n *\n * | Source                  | AST shape (outermost first)                                 |\n * | ----------------------- | ----------------------------------------------------------- |\n * | `$$$.<coll>`            | one-level access onto `DatabaseRef`                          |\n * | `$$$[\"<coll>\"]`         | one-level bracket-access onto `DatabaseRef`                  |\n * | `$$$$.<db>.<coll>`      | two-level access; inner onto `ClusterRef`                    |\n * | `$$$$[\"db\"][\"coll\"]`    | two-level bracket access; inner onto `ClusterRef`            |\n * | `$$$$.db[\"coll\"]`       | two-level mixed (bracket outer, dot inner); onto `ClusterRef` |\n * | `$$$$[\"db\"].coll`       | two-level mixed (dot outer, bracket inner); onto `ClusterRef` |\n *\n * Non-static indices (`$$$$[someVar].coll`) break the classification \u2014 we\n * can't materialise a runtime-computed db/coll name into `$lookup.from`\n * (the field is a compile-time string in MQL). Returns null for those\n * shapes; the bare-reference codegen path then surfaces the standard\n * actionable error.\n */\nexport function extractLookupTarget(receiver: Expr, ctx: GenerateCtx): LookupTarget | null {\n  const outer = staticAccess(receiver, ctx);\n  if (outer === null) return null;\n  // Single-level: $$$.<coll> / $$$[\"<coll>\"] / $$$[boundCollParam]\n  if (outer.object.type === \"DatabaseRef\") {\n    return { pos: outer.object.pos, collection: outer.name };\n  }\n  // Two-level: $$$$.<db>.<coll> and all six (literal \u00D7 literal, literal \u00D7 bound,\n  // bound \u00D7 literal, bound \u00D7 bound \u2014 across dot vs bracket) combinations.\n  const inner = staticAccess(outer.object, ctx);\n  if (inner === null) return null;\n  if (inner.object.type !== \"ClusterRef\") return null;\n  return { pos: inner.object.pos, db: inner.name, collection: outer.name };\n}\n\n/**\n * Recognise `$$$.<coll>.find(pred)` / `$$$.<coll>.filter(pred)` /\n * `$$$$.<db>.<coll>.find(pred)` / `$$$$.<db>.<coll>.filter(pred)` and all\n * their bracket variants \u2014 including `jsmql.compile`-parameter-bound\n * bracket indices (resolved through `ctx.bindings`). Returns `null` if\n * `expr` is not the shape, or if the shape is malformed (which surfaces\n * an actionable error elsewhere \u2014 see `validateLookupShape`).\n *\n * Callers in mode-gate / position-locator code paths that don't have a\n * meaningful `ctx` pass `EMPTY_CTX` \u2014 bound-bracket lookups won't be\n * detected from those paths, but those paths only run in expression\n * contexts (Filter / `jsmql.expr` / `jsmql.update`) where lookups would\n * be rejected wholesale anyway, so the trade-off is benign.\n */\nexport function detectLookupCall(expr: Expr, ctx: GenerateCtx): LookupCall | null {\n  if (expr.type !== \"MethodCall\") return null;\n  if (expr.method !== \"find\" && expr.method !== \"filter\") return null;\n  const target = extractLookupTarget(expr.object, ctx);\n  if (target === null) return null;\n  if (expr.args.length !== 1) return null;\n  const arg = expr.args[0];\n  if (arg.type !== \"Lambda\") return null;\n  return {\n    pos: target.pos,\n    callPos: expr.pos,\n    db: target.db,\n    collection: target.collection,\n    method: expr.method,\n    lambda: arg,\n  };\n}\n\n/**\n * Cheap recursive walk: does `node` (or any sub-tree thereof) contain a\n * lookup call? Used by mode-gates in `index.ts` to pre-reject lookup\n * syntax in Filter / expression / update modes with an actionable error,\n * and by `lowerWithCtx` to detect lookup-bearing `UpdateFilter` inputs so\n * they can be rerouted through the lookup-aware pipeline lowerer.\n *\n * `ctx` defaults to `EMPTY_CTX` for the mode-gate call sites that don't\n * have a meaningful context. When the caller has the real ctx\n * (`lowerWithCtx`, `rejectNestedLookup`), pass it so bound bracket-index\n * lookups (`$$$[boundParam].find(...)`) detect correctly \u2014 without the\n * ctx, the binding can't resolve and the detection silently fails.\n */\nexport function containsLookupCall(node: Expr | Pipeline | UpdateFilter, ctx: GenerateCtx = EMPTY_CTX): boolean {\n  return walkContainsLookup(node, ctx);\n}\n\nfunction walkContainsLookup(node: Expr | Pipeline | UpdateFilter | PipelineStmt | UpdateOp, ctx: GenerateCtx): boolean {\n  if (node.type === \"Pipeline\") {\n    return node.stmts.some((s) => walkContainsLookup(s, ctx));\n  }\n  if (node.type === \"UpdateFilter\") {\n    return node.ops.some((op) => walkContainsLookup(op, ctx));\n  }\n  if (node.type === \"AssignExpr\") return walkContainsLookup(node.value, ctx);\n  if (node.type === \"DeleteStmt\") return false;\n  if (node.type === \"LetDecl\") return walkContainsLookup(node.value, ctx);\n  // Expr branches that could contain nested expressions\n  const expr = node;\n  if (detectLookupCall(expr, ctx) !== null) return true;\n  if (expr.type === \"MethodCall\") {\n    if (walkContainsLookup(expr.object, ctx)) return true;\n    return walkArgsContainLookup(expr.args, ctx);\n  }\n  if (expr.type === \"CallExpression\") {\n    if (walkContainsLookup(expr.callee, ctx)) return true;\n    return walkArgsContainLookup(expr.args, ctx);\n  }\n  if (expr.type === \"OperatorCall\") return walkArgsContainLookup(expr.args, ctx);\n  if (expr.type === \"MathCall\" || expr.type === \"ObjectCall\") return walkArgsContainLookup(expr.args, ctx);\n  if (expr.type === \"MemberAccess\") return walkContainsLookup(expr.object, ctx);\n  if (expr.type === \"IndexAccess\") return walkContainsLookup(expr.object, ctx) || walkContainsLookup(expr.index, ctx);\n  if (expr.type === \"BinaryExpr\") return walkContainsLookup(expr.left, ctx) || walkContainsLookup(expr.right, ctx);\n  if (expr.type === \"UnaryExpr\") return walkContainsLookup(expr.operand, ctx);\n  if (expr.type === \"TernaryExpr\") {\n    return (\n      walkContainsLookup(expr.condition, ctx) ||\n      walkContainsLookup(expr.consequent, ctx) ||\n      walkContainsLookup(expr.alternate, ctx)\n    );\n  }\n  if (expr.type === \"Lambda\") {\n    if (expr.body !== undefined) return walkContainsLookup(expr.body, ctx);\n    if (expr.block !== undefined) return walkContainsLookup(expr.block, ctx);\n    return false;\n  }\n  if (expr.type === \"ArrayLiteral\") {\n    for (const el of expr.elements) {\n      if (el.type === \"SpreadElement\") {\n        if (walkContainsLookup(el.argument, ctx)) return true;\n      } else if (\n        walkContainsLookup(el as Expr | UpdateOp | { type: \"LetDecl\"; name: string; value: Expr; pos: number }, ctx)\n      ) {\n        return true;\n      }\n    }\n    return false;\n  }\n  if (expr.type === \"ObjectLiteral\") {\n    for (const entry of expr.entries) {\n      if (entry.type === \"SpreadElement\") {\n        if (walkContainsLookup(entry.argument, ctx)) return true;\n      } else {\n        if (entry.key.kind === \"computed\" && walkContainsLookup(entry.key.expr, ctx)) return true;\n        if (walkContainsLookup(entry.value, ctx)) return true;\n      }\n    }\n    return false;\n  }\n  if (expr.type === \"TemplateLiteral\") return expr.expressions.some((e) => walkContainsLookup(e, ctx));\n  if (expr.type === \"TypeofExpr\") return walkContainsLookup(expr.operand, ctx);\n  if (expr.type === \"NewDate\") return expr.args.some((a) => walkContainsLookup(a, ctx));\n  if (expr.type === \"NewSet\") return expr.arg ? walkContainsLookup(expr.arg, ctx) : false;\n  if (expr.type === \"TypeCast\") return walkContainsLookup(expr.arg, ctx);\n  if (expr.type === \"ArrayFrom\")\n    return walkContainsLookup(expr.input, ctx) || (expr.mapFn ? walkContainsLookup(expr.mapFn, ctx) : false);\n  if (expr.type === \"NumberStatic\") return walkContainsLookup(expr.arg, ctx);\n  if (expr.type === \"DateUTC\") return expr.args.some((a) => walkContainsLookup(a, ctx));\n  return false;\n}\n\nfunction walkArgsContainLookup(args: CallArg[], ctx: GenerateCtx): boolean {\n  for (const a of args) {\n    if (a.type === \"SpreadElement\") {\n      if (walkContainsLookup(a.argument, ctx)) return true;\n    } else if (walkContainsLookup(a, ctx)) return true;\n  }\n  return false;\n}\n\n// \u2500\u2500 Validation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Walk `expr` back to a context-ref leaf and report which prefix it's rooted\n * at, alongside the spelling used in error messages. Returns null if the\n * receiver isn't context-ref-shaped. Distinct from `extractLookupTarget` \u2014\n * that helper requires a *valid* one-or-two-level shape with static names;\n * this one is used to gate the validation-error throw site so a malformed\n * lookup-shaped receiver (wrong method, dynamic indices, missing levels)\n * still produces the targeted error instead of falling through to the\n * generic codegen one.\n */\nfunction classifyLookupReceiver(receiver: Expr): { spelling: string } | null {\n  let node: Expr = receiver;\n  for (;;) {\n    if (node.type === \"DatabaseRef\") return { spelling: \"$$$.<coll>\" };\n    if (node.type === \"ClusterRef\") return { spelling: \"$$$$.<db>.<coll>\" };\n    if (node.type === \"MemberAccess\" || node.type === \"IndexAccess\") {\n      node = node.object;\n      continue;\n    }\n    return null;\n  }\n}\n\n/**\n * If `expr` looks like a lookup but is malformed (wrong method, wrong arity,\n * non-lambda arg), throw the targeted error. Used by the prologue extractor\n * before falling through to a generic walk.\n */\nexport function validateLookupShape(expr: Expr): void {\n  if (expr.type !== \"MethodCall\") return;\n  const shape = classifyLookupReceiver(expr.object);\n  if (shape === null) return;\n  // We're on a `$$$.<coll>.<method>(...)` or `$$$$.<db>.<coll>.<method>(...)` chain.\n  const spell = shape.spelling;\n  if (expr.method !== \"find\" && expr.method !== \"filter\") {\n    const hint = didYouMean(expr.method, [\"find\", \"filter\"], (s) => `.${s}`);\n    throw new CodegenError(\n      `'${spell}' supports .find(pred) and .filter(pred), not .${expr.method}().${hint} ` +\n        `For richer queries, use a block-body lambda: ` +\n        `\\`${spell}.filter(o => { $match(...); $sort(...); ... })\\`.`,\n      expr.pos,\n    );\n  }\n  if (expr.args.length !== 1) {\n    throw new CodegenError(\n      `.${expr.method}(predicate) takes exactly one argument (a single-parameter arrow), got ${expr.args.length}.`,\n      expr.pos,\n    );\n  }\n  const arg = expr.args[0];\n  if (arg.type !== \"Lambda\") {\n    throw new CodegenError(\n      `.${expr.method}(predicate) requires an arrow predicate, e.g. \\`.${expr.method}(o => o._id === $.userId)\\`.`,\n      \"pos\" in arg ? arg.pos : expr.pos,\n    );\n  }\n  if (arg.params.length !== 1) {\n    throw new CodegenError(\n      `.${expr.method}(predicate) takes a single-parameter arrow (the foreign document), got ${arg.params.length}.`,\n      arg.pos,\n    );\n  }\n}\n\n// \u2500\u2500 Slot allocator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Compiler-owned namespace; same field jsmql's pipeline-scoped `let` uses. */\nconst LET_NAMESPACE = \"__jsmql\";\n\n/**\n * Per-pipeline counter shared across `extractLookupCalls` invocations so\n * `__jsmql.__lookup1` / `__lookup2` / \u2026 stay distinct within one pipeline.\n * The caller owns the counter.\n */\nexport type SlotAllocator = () => string;\n\nexport function createSlotAllocator(): SlotAllocator {\n  let n = 0;\n  return () => {\n    n += 1;\n    return `${LET_NAMESPACE}.__lookup${n}`;\n  };\n}\n\n// \u2500\u2500 Path classification (for let extraction) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Walk down `expr` (an AST sub-tree at `MemberAccess` / `IndexAccess` /\n * `FieldRef` / `ParamRef` shape) and report whether it's a path rooted at\n * the local doc (`$.\u2026`) or at the foreign-doc lambda param (`o.\u2026`).\n *\n * Returns the dotted path segments alongside the root kind. IndexAccess\n * with a static string is folded into the path; non-static indices break\n * the classification (the sub-tree is not a foldable path).\n */\ntype ClassifiedPath =\n  | { kind: \"local\"; segments: string[] }\n  | { kind: \"foreign\"; segments: string[] }\n  | {\n      // An outer pipeline-scoped `let` binding referenced inside the predicate\n      // (optionally with member access on it). The let materialises under\n      // `__jsmql.<bindingName>` on each outer doc; `fieldPath` is the full\n      // resolved path including any `.member` chain (e.g.\n      // `__jsmql.user._id` for `user._id` where `user` is the binding).\n      // `segments` is the access chain starting at the binding name \u2014\n      // used for letVar-naming via `segments[last]`, mirroring the\n      // local-path convention.\n      kind: \"outerLet\";\n      segments: string[];\n      fieldPath: string;\n    };\n\nfunction classifyPath(\n  expr: Expr,\n  foreignParam: string,\n  outerLets?: ReadonlyMap<string, string>,\n): ClassifiedPath | null {\n  if (expr.type === \"FieldRef\") return { kind: \"local\", segments: [expr.path] };\n  if (expr.type === \"ParamRef\") {\n    if (expr.name === foreignParam) return { kind: \"foreign\", segments: [] };\n    if (outerLets !== undefined && outerLets.has(expr.name)) {\n      const fieldPath = outerLets.get(expr.name);\n      if (fieldPath !== undefined) {\n        return { kind: \"outerLet\", segments: [expr.name], fieldPath };\n      }\n    }\n    return null;\n  }\n  if (expr.type === \"MemberAccess\") {\n    const inner = classifyPath(expr.object, foreignParam, outerLets);\n    if (inner === null) return null;\n    if (inner.kind === \"outerLet\") {\n      return {\n        kind: \"outerLet\",\n        segments: [...inner.segments, expr.member],\n        fieldPath: `${inner.fieldPath}.${expr.member}`,\n      };\n    }\n    return { kind: inner.kind, segments: [...inner.segments, expr.member] };\n  }\n  if (expr.type === \"IndexAccess\" && expr.index.type === \"StringLiteral\") {\n    const inner = classifyPath(expr.object, foreignParam, outerLets);\n    if (inner === null) return null;\n    if (inner.kind === \"outerLet\") {\n      return {\n        kind: \"outerLet\",\n        segments: [...inner.segments, expr.index.value],\n        fieldPath: `${inner.fieldPath}.${expr.index.value}`,\n      };\n    }\n    return { kind: inner.kind, segments: [...inner.segments, expr.index.value] };\n  }\n  return null;\n}\n\n// \u2500\u2500 Predicate translation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type BasicFormPredicate = { kind: \"basic\"; localField: string; foreignField: string };\n\nexport type PipelineFormPredicate = {\n  kind: \"pipeline\";\n  /** let-vars to expose at the $lookup level. Key = letVarName; value = MQL field path string (e.g. \"$_id\"). */\n  letVars: Record<string, string>;\n  /** Stages making up the $lookup.pipeline body. */\n  pipeline: object[];\n};\n\n/**\n * Translate a lookup-call's lambda into either the basic-form fields\n * (when the body is a single `===` between a foreign-path and a `$.`\n * local-path) or the correlated-pipeline form (everything else).\n *\n * `outerCtx` is the GenerateCtx the consuming pipeline is running under\n * \u2014 passed through so sub-pipeline codegen sees the same function-form\n * `bindings` (compile-time constants cross sub-pipeline boundaries; lets\n * do not, per `freshSubPipelineCtx`).\n */\nexport function translatePredicate(\n  call: LookupCall,\n  outerCtx: GenerateCtx,\n  lowerBlock: SubPipelineLowerer,\n  enclosing: EnclosingLookupContext = EMPTY_ENCLOSING,\n): BasicFormPredicate | PipelineFormPredicate {\n  const { lambda } = call;\n  const foreignParam = lambda.params[0];\n  const outerLets = outerCtx.pipelineLets;\n\n  // \u2500\u2500 Expression body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  if (lambda.body !== undefined) {\n    // Step 1: pre-rewrite enclosing-foreign-param refs to FieldRefs so the\n    // inner's classifyPath sees them as local paths (auto-let captured into\n    // the inner's $lookup.let). No-op at the top level.\n    const preRewritten = rewriteEnclosingForeignParams(lambda.body, enclosing.foreignParams);\n\n    // Basic-form is only valid at the top level. Nested lookups can't use\n    // basic-form because their `localField` would be a path on the\n    // enclosing pipeline's local doc, not on the outermost doc \u2014 force\n    // pipeline-form so all the let-coordination plumbing kicks in.\n    if (enclosing.foreignParams.length === 0) {\n      const basic = tryBasicForm(preRewritten, foreignParam, outerLets);\n      if (basic !== null) return basic;\n    }\n\n    // Pipeline-form with auto-`let` extraction.\n    const { rewritten, letVars } = extractLetsFromExpr(preRewritten, foreignParam, outerLets);\n\n    // Step 2: materialise nested lookups in the now-rewritten body. The\n    // enclosing context grows by one level: this lookup's foreignParam plus\n    // its newly-allocated letVars are now in scope for any deeper lookups.\n    const innerEnclosing: EnclosingLookupContext = {\n      foreignParams: [...enclosing.foreignParams, foreignParam],\n      inScopeLetNames: new Set([...enclosing.inScopeLetNames, ...Object.keys(letVars)]),\n    };\n    const localAllocSlot = createSlotAllocator();\n    const { stages: nestedStages, rewritten: lookupFree } = extractLookupCalls(\n      rewritten,\n      outerCtx,\n      localAllocSlot,\n      lowerBlock,\n      innerEnclosing,\n    );\n\n    // Codegen context: our own letVar names PLUS enclosing-in-scope names\n    // are all `lambdaParams` so codegen emits `$$<name>` correctly.\n    const subCtx = makeSubPipelineCtx(outerCtx, [...Object.keys(letVars), ...enclosing.inScopeLetNames]);\n    const matchBody = generateWithCtx(lookupFree, subCtx);\n    return { kind: \"pipeline\", letVars, pipeline: [...nestedStages, { $match: { $expr: matchBody } }] };\n  }\n\n  // \u2500\u2500 Block body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  if (lambda.block !== undefined) {\n    // Block-body nesting is a separate slice of work \u2014 each statement\n    // may carry its own lookup, and the block's lowering already runs\n    // `extractLookupCalls` for stage bodies. For now, only expression-body\n    // lookups support nesting; block-body nested lookups would need ctx-\n    // threading through `lowerBlock` (tracked as the next step). Reject\n    // EITHER condition: (a) this lookup is itself nested inside another\n    // (enclosing non-empty), or (b) this lookup is top-level but its block\n    // body itself contains a nested lookup call.\n    if (enclosing.foreignParams.length > 0 || containsLookupCall(lambda.block, outerCtx)) {\n      // [DEF-023] block-body nested lookups\n      throw new CodegenError(\n        `Nested lookup inside another lookup's block-body lambda is not yet supported. ` +\n          `Use an expression-body lambda for the outer lookup, or hoist the inner lookup to a sibling stage.`,\n        lambda.pos,\n      );\n    }\n    const { rewritten, letVars } = extractLetsFromPipeline(lambda.block, foreignParam, outerLets);\n    const subCtx = makeSubPipelineCtx(outerCtx, Object.keys(letVars));\n    const stages = lowerBlock(rewritten, subCtx);\n    return { kind: \"pipeline\", letVars, pipeline: stages };\n  }\n\n  throw new CodegenError(\n    `.${call.method}(predicate) lambda is missing a body \u2014 internal parser bug; please report.`,\n    lambda.pos,\n  );\n}\n\nfunction makeSubPipelineCtx(outerCtx: GenerateCtx, letVarNames: string[]): GenerateCtx {\n  const fresh = freshSubPipelineCtx(outerCtx);\n  if (letVarNames.length === 0) return fresh;\n  return { ...fresh, lambdaParams: new Set([...fresh.lambdaParams, ...letVarNames]) };\n}\n\n/**\n * Translate a `.filter(<lambda>)` predicate into the pipeline-form\n * components \u2014 `{ letVars, pipelineBody }` \u2014 usable as a `$lookup.let` +\n * `$lookup.pipeline` payload OR as the seed of a longer sub-pipeline that\n * chain methods will extend. Exported so callers outside this module\n * (`pipeline.ts`'s lookup-pivot and chain-extension paths) can build\n * pipeline-form lookups without re-implementing the predicate translation.\n *\n * Same algorithm as `translatePredicate`'s pipeline branch \u2014 expression\n * bodies route through `extractLetsFromExpr` (auto-`let` extraction +\n * foreign-path rewriting) and emit a `$match: { $expr: <translated> }`;\n * block bodies route through `extractLetsFromPipeline` + the caller-\n * supplied `lowerBlock` for the full sub-pipeline shape.\n */\nexport function buildPipelineFormPredicate(\n  lambda: Lambda,\n  outerCtx: GenerateCtx,\n  lowerBlock: SubPipelineLowerer,\n  enclosing: EnclosingLookupContext = EMPTY_ENCLOSING,\n): { letVars: Record<string, string>; pipelineBody: object[] } {\n  const foreignParam = lambda.params[0];\n  const outerLets = outerCtx.pipelineLets;\n  if (lambda.body !== undefined) {\n    const preRewritten = rewriteEnclosingForeignParams(lambda.body, enclosing.foreignParams);\n    const { rewritten, letVars } = extractLetsFromExpr(preRewritten, foreignParam, outerLets);\n    const innerEnclosing: EnclosingLookupContext = {\n      foreignParams: [...enclosing.foreignParams, foreignParam],\n      inScopeLetNames: new Set([...enclosing.inScopeLetNames, ...Object.keys(letVars)]),\n    };\n    const localAllocSlot = createSlotAllocator();\n    const { stages: nestedStages, rewritten: lookupFree } = extractLookupCalls(\n      rewritten,\n      outerCtx,\n      localAllocSlot,\n      lowerBlock,\n      innerEnclosing,\n    );\n    const subCtx = makeSubPipelineCtx(outerCtx, [...Object.keys(letVars), ...enclosing.inScopeLetNames]);\n    return { letVars, pipelineBody: [...nestedStages, { $match: { $expr: generateWithCtx(lookupFree, subCtx) } }] };\n  }\n  if (lambda.block !== undefined) {\n    if (enclosing.foreignParams.length > 0) {\n      // [DEF-023] block-body nested lookups\n      throw new CodegenError(\n        `Nested lookup inside another lookup's block-body lambda is not yet supported. ` +\n          `Use an expression-body lambda for the outer lookup, or hoist the inner lookup to a sibling stage.`,\n        lambda.pos,\n      );\n    }\n    const { rewritten, letVars } = extractLetsFromPipeline(lambda.block, foreignParam, outerLets);\n    const subCtx = makeSubPipelineCtx(outerCtx, Object.keys(letVars));\n    return { letVars, pipelineBody: lowerBlock(rewritten, subCtx) };\n  }\n  throw new CodegenError(`Predicate lambda is missing a body \u2014 internal parser bug; please report.`, lambda.pos);\n}\n\n/**\n * Does the predicate reference any outer-doc context \u2014 either a `$.<field>`\n * path on the current document, or an in-scope `let` binding (a name bound\n * via `let foo = \u2026` in the surrounding pipeline)? Used by `pipeline.ts` to\n * decide whether a `$$ = $$$.<coll>.filter(<pred>)` source-switch needs the\n * `$lookup`-pivot lowering (when the predicate correlates per-outer-doc) vs\n * the `$limit:0 + $unionWith` lowering (when it's a flat source-collection\n * scan).\n *\n * Detection mirrors what `extractLetsFromExpr` would produce \u2014 if there are\n * any `$.<field>` paths OR outer-let references in the body that would be\n * hoisted into `$lookup.let` vars, this returns true.\n */\nexport function predicateReferencesOuterDoc(lambda: Lambda, outerCtx: GenerateCtx): boolean {\n  if (lambda.params.length !== 1) return false;\n  const foreignParam = lambda.params[0];\n  const outerLets = outerCtx.pipelineLets;\n  if (lambda.body !== undefined) {\n    const { letVars } = extractLetsFromExpr(lambda.body, foreignParam, outerLets);\n    return Object.keys(letVars).length > 0;\n  }\n  if (lambda.block !== undefined) {\n    const { letVars } = extractLetsFromPipeline(lambda.block, foreignParam, outerLets);\n    return Object.keys(letVars).length > 0;\n  }\n  return false;\n}\n\n/**\n * Detect the basic-form predicate shape: body is `===` with one side a\n * foreign-path and the other a `$.` local path. Returns null for any\n * richer shape so the caller falls back to pipeline form.\n *\n * Only `===` is accepted here \u2014 never `==`. jsmql's project-wide rule\n * (see LANGUAGE.md, `===` vs `==` table) restricts `==` to comparisons\n * against `null`; anything else is rejected with a targeted \"use `===`\"\n * error. Carving an exception for lookup predicates would create exactly\n * the kind of inconsistency the rule exists to prevent. A user-written\n * `o.userId == $._id` falls through to pipeline form, where the\n * sub-pipeline codegen of the `$expr` body hits the standard `==`-only-\n * against-null check and throws the same error the user would get\n * anywhere else in jsmql.\n */\nfunction tryBasicForm(\n  body: Expr,\n  foreignParam: string,\n  outerLets?: ReadonlyMap<string, string>,\n): BasicFormPredicate | null {\n  if (body.type !== \"BinaryExpr\") return null;\n  if (body.op !== \"===\") return null;\n  const leftPath = classifyPath(body.left, foreignParam, outerLets);\n  const rightPath = classifyPath(body.right, foreignParam, outerLets);\n  if (leftPath === null || rightPath === null) return null;\n  // \"Local\" for basic-form purposes means anything that resolves to a field\n  // path on the OUTER doc \u2014 either a `$.<field>` ref OR an outer-let ref\n  // (whose materialised path lives at `__jsmql.<binding>` on each outer doc).\n  function localFieldFor(p: ClassifiedPath): string | null {\n    if (p.kind === \"local\" && p.segments.length > 0) return p.segments.join(\".\");\n    if (p.kind === \"outerLet\") return p.fieldPath;\n    return null;\n  }\n  if (leftPath.kind === \"foreign\" && leftPath.segments.length > 0) {\n    const local = localFieldFor(rightPath);\n    if (local !== null) {\n      return { kind: \"basic\", foreignField: leftPath.segments.join(\".\"), localField: local };\n    }\n  }\n  if (rightPath.kind === \"foreign\" && rightPath.segments.length > 0) {\n    const local = localFieldFor(leftPath);\n    if (local !== null) {\n      return { kind: \"basic\", foreignField: rightPath.segments.join(\".\"), localField: local };\n    }\n  }\n  return null;\n}\n\n// \u2500\u2500 Let extraction (AST rewriter) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype LetAllocator = {\n  /** Records \"userId\" \u2192 \"$userId\"; on second call with same path, returns the existing name. */\n  allocateForLocalPath: (segments: string[]) => string;\n  /**\n   * Outer pipeline-scoped `let` binding referenced inside the predicate.\n   * `segments` is the access chain rooted at the binding name (e.g.\n   * `[\"user\", \"_id\"]` for `user._id`); `fieldPath` is the full materialised\n   * path on the outer doc (e.g. `\"__jsmql.user._id\"`). The allocated letVar\n   * name is `segments[last]` \u2014 same convention as `allocateForLocalPath` \u2014\n   * uniquified on collision.\n   */\n  allocateForOuterLet: (segments: string[], fieldPath: string) => string;\n  /** Final mapping for emit into `$lookup.let`. */\n  letVars: () => Record<string, string>;\n};\n\nfunction createLetAllocator(): LetAllocator {\n  const byPath = new Map<string, string>();\n  const used = new Set<string>();\n  const out: Record<string, string> = {};\n  function uniqueName(preferred: string): string {\n    if (!used.has(preferred)) return preferred;\n    let n = 2;\n    let candidate = `${preferred}_${n}`;\n    while (used.has(candidate)) {\n      n += 1;\n      candidate = `${preferred}_${n}`;\n    }\n    return candidate;\n  }\n  return {\n    allocateForLocalPath(segments: string[]): string {\n      const dotted = segments.join(\".\");\n      const existing = byPath.get(dotted);\n      if (existing !== undefined) return existing;\n      const base = segments[segments.length - 1];\n      const name = uniqueName(base);\n      used.add(name);\n      byPath.set(dotted, name);\n      out[name] = `$${dotted}`;\n      return name;\n    },\n    allocateForOuterLet(segments: string[], fieldPath: string): string {\n      const existing = byPath.get(fieldPath);\n      if (existing !== undefined) return existing;\n      const base = segments[segments.length - 1];\n      const name = uniqueName(base);\n      used.add(name);\n      byPath.set(fieldPath, name);\n      out[name] = `$${fieldPath}`;\n      return name;\n    },\n    letVars: () => out,\n  };\n}\n\nexport function extractLetsFromExpr(\n  body: Expr,\n  foreignParam: string,\n  outerLets?: ReadonlyMap<string, string>,\n): { rewritten: Expr; letVars: Record<string, string> } {\n  const allocator = createLetAllocator();\n  const rewritten = transformExpr(body, foreignParam, allocator, outerLets);\n  return { rewritten, letVars: allocator.letVars() };\n}\n\nexport function extractLetsFromPipeline(\n  block: Pipeline,\n  foreignParam: string,\n  outerLets?: ReadonlyMap<string, string>,\n): { rewritten: Pipeline; letVars: Record<string, string> } {\n  const allocator = createLetAllocator();\n  const stmts: PipelineStmt[] = block.stmts.map((s) => transformStmt(s, foreignParam, allocator, outerLets));\n  return { rewritten: { type: \"Pipeline\", stmts, pos: block.pos }, letVars: allocator.letVars() };\n}\n\n/**\n * Emit the `$match` stages for a translated expression-body predicate. Lifted\n * verbatim from the union/facet/out translators, which all needed the same\n * four-way split: vacuous predicate \u2192 no stage; pure query \u2192 `{ $match: query }`;\n * pure residual \u2192 `{ $match: { $expr } }`; both \u2192 merged. Keeping it in one\n * place means the index-friendly/`$expr`-residual emission can't drift between\n * the sub-pipeline translators.\n */\nexport function matchStagesFromTranslation(t: MatchTranslation, subCtx: GenerateCtx): object[] {\n  const merged = mergeTranslatedQuery(t, subCtx);\n  return merged === null ? [] : [{ $match: merged }]; // null = vacuous predicate, skip the $match\n}\n\n/**\n * Lower a single-parameter predicate lambda \u2014 the foreign/current document is\n * the param \u2014 into sub-pipeline stages. Shared by the `$unionWith`, `$facet`,\n * and `$out` translators, which differ only in (a) the message thrown when the\n * predicate references the *local* doc (`$.<field>`, which would need a `let`\n * slot the target stage lacks) and (b) which fresh sub-pipeline ctx they build.\n * Both are injected; the expr-body / block-body / missing-body skeleton and the\n * `$match` emission are identical and live here.\n *\n * The caller validates the lambda's parameter count first (with its own\n * stage-specific message) \u2014 this helper assumes `lambda.params[0]` is the\n * document parameter.\n */\nexport function lowerLambdaPredicate(\n  lambda: Lambda,\n  outerCtx: GenerateCtx,\n  lowerBlock: SubPipelineLowerer,\n  opts: {\n    freshCtx: (outer: GenerateCtx) => GenerateCtx;\n    onLocalRef: (letVars: Record<string, string>, param: string, pos: number) => never;\n    missingBody: () => never;\n  },\n): object[] {\n  const param = lambda.params[0];\n\n  // Expression body \u2192 query-language translation + `$match`.\n  if (lambda.body !== undefined) {\n    const { rewritten, letVars } = extractLetsFromExpr(lambda.body, param);\n    if (Object.keys(letVars).length > 0) opts.onLocalRef(letVars, param, lambda.pos);\n    const subCtx = opts.freshCtx(outerCtx);\n    const t = translateMatchBody(rewritten, { bindings: subCtx.bindings });\n    return matchStagesFromTranslation(t, subCtx);\n  }\n\n  // Block body \u2192 each statement becomes a stage via the caller's lowerer.\n  if (lambda.block !== undefined) {\n    const { rewritten, letVars } = extractLetsFromPipeline(lambda.block, param);\n    if (Object.keys(letVars).length > 0) opts.onLocalRef(letVars, param, lambda.pos);\n    const subCtx = opts.freshCtx(outerCtx);\n    return lowerBlock(rewritten, subCtx);\n  }\n\n  return opts.missingBody();\n}\n\nfunction transformStmt(\n  stmt: PipelineStmt,\n  foreignParam: string,\n  allocator: LetAllocator,\n  outerLets: ReadonlyMap<string, string> | undefined,\n): PipelineStmt {\n  if (stmt.type === \"LetDecl\") {\n    return {\n      type: \"LetDecl\",\n      name: stmt.name,\n      value: transformExpr(stmt.value, foreignParam, allocator, outerLets),\n      pos: stmt.pos,\n    };\n  }\n  if (stmt.type === \"UpdateFilter\") {\n    const ops: UpdateOp[] = stmt.ops.map((op) => {\n      if (op.type === \"AssignExpr\") {\n        return {\n          type: \"AssignExpr\",\n          target: transformExpr(op.target, foreignParam, allocator, outerLets),\n          value: transformExpr(op.value, foreignParam, allocator, outerLets),\n          pos: op.pos,\n        };\n      }\n      // DeleteStmt\n      return { type: \"DeleteStmt\", target: transformExpr(op.target, foreignParam, allocator, outerLets), pos: op.pos };\n    });\n    return { type: \"UpdateFilter\", ops, pos: stmt.pos };\n  }\n  return transformExpr(stmt as Expr, foreignParam, allocator, outerLets);\n}\n\n/**\n * Recursive AST rewriter. At each visited node:\n *   - If the node is a `classifyPath`-able sub-tree:\n *     - \"local\" root \u2192 swap for a `ParamRef` whose name is the allocated\n *       let-var (codegen lowers it to `$$<letVar>` \u2014 exactly the MQL\n *       binding the sub-pipeline needs).\n *     - \"foreign\" root \u2192 swap for a bare `FieldRef(path)` (lowers to\n *       `\"$path\"` inside the sub-pipeline, where the foreign doc is the\n *       root).\n *   - Otherwise recurse into children, producing a fresh node with\n *     transformed sub-trees.\n *\n * Nested lambdas inside the predicate body keep their own params; we\n * stop walking into their bodies because their scope is distinct. (A\n * nested `$$$.x.find/filter(...)` is detected separately by the\n * pipeline integration, which rejects it in v1 \u2014 see plan \u00A75.)\n */\nfunction transformExpr(\n  expr: Expr,\n  foreignParam: string,\n  allocator: LetAllocator,\n  outerLets: ReadonlyMap<string, string> | undefined,\n): Expr {\n  const classified = classifyPath(expr, foreignParam, outerLets);\n  if (classified !== null) {\n    if (classified.kind === \"local\") {\n      const letVar = allocator.allocateForLocalPath(classified.segments);\n      return { type: \"ParamRef\", name: letVar, pos: expr.pos } as ParamRef;\n    }\n    if (classified.kind === \"outerLet\") {\n      const letVar = allocator.allocateForOuterLet(classified.segments, classified.fieldPath);\n      return { type: \"ParamRef\", name: letVar, pos: expr.pos } as ParamRef;\n    }\n    // Foreign path. Bare `o` alone is not yet supported (no $$ROOT lowering).\n    if (classified.segments.length === 0) {\n      throw new CodegenError(\n        `Bare lambda parameter '${foreignParam}' in a $lookup predicate is not yet supported \u2014 use \\`${foreignParam}.<field>\\` to reference a foreign document field.`,\n        expr.pos,\n      );\n    }\n    return { type: \"FieldRef\", path: classified.segments.join(\".\"), pos: expr.pos } as FieldRef;\n  }\n  return mapChildren(expr, foreignParam, allocator, outerLets);\n}\n\nfunction mapChildren(\n  expr: Expr,\n  foreignParam: string,\n  allocator: LetAllocator,\n  outerLets: ReadonlyMap<string, string> | undefined,\n): Expr {\n  switch (expr.type) {\n    case \"FieldRef\":\n    case \"CollectionRef\":\n    case \"DatabaseRef\":\n    case \"ClusterRef\":\n    case \"NumberLiteral\":\n    case \"BigIntLiteral\":\n    case \"StringLiteral\":\n    case \"BooleanLiteral\":\n    case \"NullLiteral\":\n    case \"UndefinedLiteral\":\n    case \"RegexLiteral\":\n    case \"ParamRef\":\n    case \"TypeCastRef\":\n    case \"MathConst\":\n    case \"MathCallRef\":\n    case \"DateNow\":\n      return expr;\n    case \"BinaryExpr\":\n      return {\n        type: \"BinaryExpr\",\n        op: expr.op,\n        left: transformExpr(expr.left, foreignParam, allocator, outerLets),\n        right: transformExpr(expr.right, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n      };\n    case \"UnaryExpr\":\n      return {\n        type: \"UnaryExpr\",\n        op: expr.op,\n        operand: transformExpr(expr.operand, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n      };\n    case \"TernaryExpr\":\n      return {\n        type: \"TernaryExpr\",\n        condition: transformExpr(expr.condition, foreignParam, allocator, outerLets),\n        consequent: transformExpr(expr.consequent, foreignParam, allocator, outerLets),\n        alternate: transformExpr(expr.alternate, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n      };\n    case \"MemberAccess\":\n      return {\n        type: \"MemberAccess\",\n        object: transformExpr(expr.object, foreignParam, allocator, outerLets),\n        member: expr.member,\n        pos: expr.pos,\n        ...(expr.optional && { optional: true }),\n      };\n    case \"IndexAccess\":\n      return {\n        type: \"IndexAccess\",\n        object: transformExpr(expr.object, foreignParam, allocator, outerLets),\n        index: transformExpr(expr.index, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n        ...(expr.optional && { optional: true }),\n      };\n    case \"MethodCall\":\n      // Note on nested lookups: when this MethodCall is itself a lookup call\n      // (`$$$.<coll>.find/filter(...)`), the args[0] is its OWN lambda. The\n      // recursive `transformExpr` below walks INTO the inner lambda's body\n      // with the OUTER's foreignParam still in scope \u2014 which is what we\n      // want: a `outerForeign.<x>` ref inside the inner body classifies as\n      // foreign and rewrites to `FieldRef(<x>)`, exactly the pre-rewrite\n      // that `rewriteEnclosingForeignParams` would apply in the nested-\n      // materialisation step. Inner-foreign refs (`inner.x`) don't match\n      // the outer's foreignParam, so they pass through unchanged.\n      return {\n        type: \"MethodCall\",\n        object: transformExpr(expr.object, foreignParam, allocator, outerLets),\n        method: expr.method,\n        args: transformCallArgs(expr.args, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n        ...(expr.optional && { optional: true }),\n      };\n    case \"CallExpression\":\n      return {\n        type: \"CallExpression\",\n        callee: transformExpr(expr.callee, foreignParam, allocator, outerLets),\n        args: transformCallArgs(expr.args, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n      };\n    case \"OperatorCall\":\n      return {\n        type: \"OperatorCall\",\n        name: expr.name,\n        style: expr.style,\n        args: transformCallArgs(expr.args, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n      };\n    case \"Lambda\":\n      // Nested lambdas shadow the foreign param if they reuse the name; otherwise\n      // their references resolve through the outer scope. Conservatively, we\n      // recurse with the same foreign-param so $.x refs inside still hoist out.\n      if (expr.body !== undefined) {\n        return {\n          type: \"Lambda\",\n          params: expr.params,\n          body: transformExpr(expr.body, foreignParam, allocator, outerLets),\n          pos: expr.pos,\n        };\n      }\n      // Block-body in a nested position would be unusual (only the outermost\n      // lookup-callback parses a block body). Pass through unchanged.\n      return expr;\n    case \"ArrayLiteral\":\n      return {\n        type: \"ArrayLiteral\",\n        elements: expr.elements.map((el): ArrayElement => {\n          if (el.type === \"SpreadElement\") {\n            return {\n              type: \"SpreadElement\",\n              argument: transformExpr(el.argument, foreignParam, allocator, outerLets),\n              pos: el.pos,\n            };\n          }\n          if (el.type === \"AssignExpr\") {\n            return {\n              type: \"AssignExpr\",\n              target: transformExpr(el.target, foreignParam, allocator, outerLets),\n              value: transformExpr(el.value, foreignParam, allocator, outerLets),\n              pos: el.pos,\n            };\n          }\n          if (el.type === \"DeleteStmt\") {\n            return {\n              type: \"DeleteStmt\",\n              target: transformExpr(el.target, foreignParam, allocator, outerLets),\n              pos: el.pos,\n            };\n          }\n          if (el.type === \"LetDecl\") {\n            return {\n              type: \"LetDecl\",\n              name: el.name,\n              value: transformExpr(el.value, foreignParam, allocator, outerLets),\n              pos: el.pos,\n            };\n          }\n          return transformExpr(el as Expr, foreignParam, allocator, outerLets);\n        }),\n        pos: expr.pos,\n      };\n    case \"ObjectLiteral\":\n      return {\n        type: \"ObjectLiteral\",\n        entries: expr.entries.map((entry): ObjectEntry => {\n          if (entry.type === \"SpreadElement\") {\n            return {\n              type: \"SpreadElement\",\n              argument: transformExpr(entry.argument, foreignParam, allocator, outerLets),\n              pos: entry.pos,\n            };\n          }\n          const kv: KeyValueEntry = {\n            type: \"KeyValueEntry\",\n            key:\n              entry.key.kind === \"computed\"\n                ? { kind: \"computed\", expr: transformExpr(entry.key.expr, foreignParam, allocator, outerLets) }\n                : entry.key,\n            value: transformExpr(entry.value, foreignParam, allocator, outerLets),\n            pos: entry.pos,\n          };\n          return kv;\n        }),\n        pos: expr.pos,\n      };\n    case \"TemplateLiteral\":\n      return {\n        type: \"TemplateLiteral\",\n        quasis: expr.quasis,\n        expressions: expr.expressions.map((e) => transformExpr(e, foreignParam, allocator, outerLets)),\n        pos: expr.pos,\n      };\n    case \"TypeofExpr\":\n      return {\n        type: \"TypeofExpr\",\n        operand: transformExpr(expr.operand, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n      };\n    case \"NewDate\":\n      return {\n        type: \"NewDate\",\n        args: expr.args.map((a) => transformExpr(a, foreignParam, allocator, outerLets)),\n        pos: expr.pos,\n      };\n    case \"NewSet\":\n      return {\n        type: \"NewSet\",\n        arg: expr.arg !== null ? transformExpr(expr.arg, foreignParam, allocator, outerLets) : null,\n        pos: expr.pos,\n      };\n    case \"TypeCast\":\n      return {\n        type: \"TypeCast\",\n        cast: expr.cast,\n        arg: transformExpr(expr.arg, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n      };\n    case \"MathCall\":\n      return {\n        type: \"MathCall\",\n        method: expr.method,\n        args: transformCallArgs(expr.args, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n      };\n    case \"ObjectCall\":\n      return {\n        type: \"ObjectCall\",\n        method: expr.method,\n        args: transformCallArgs(expr.args, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n      };\n    case \"ArrayFrom\":\n      return {\n        type: \"ArrayFrom\",\n        input: transformExpr(expr.input, foreignParam, allocator, outerLets),\n        mapFn: expr.mapFn !== null ? transformExpr(expr.mapFn, foreignParam, allocator, outerLets) : null,\n        pos: expr.pos,\n      };\n    case \"NumberStatic\":\n      return {\n        type: \"NumberStatic\",\n        method: expr.method,\n        arg: transformExpr(expr.arg, foreignParam, allocator, outerLets),\n        pos: expr.pos,\n      };\n    case \"DateUTC\":\n      return {\n        type: \"DateUTC\",\n        args: expr.args.map((a) => transformExpr(a, foreignParam, allocator, outerLets)),\n        pos: expr.pos,\n      };\n  }\n}\n\nfunction transformCallArgs(\n  args: CallArg[],\n  foreignParam: string,\n  allocator: LetAllocator,\n  outerLets: ReadonlyMap<string, string> | undefined,\n): CallArg[] {\n  return args.map((a): CallArg => {\n    if (a.type === \"SpreadElement\") {\n      return {\n        type: \"SpreadElement\",\n        argument: transformExpr(a.argument, foreignParam, allocator, outerLets),\n        pos: a.pos,\n      };\n    }\n    return transformExpr(a, foreignParam, allocator, outerLets);\n  });\n}\n\n// \u2500\u2500 Lowering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Build the `$lookup` (+ optional `$set { $first }`) stage list for a single\n * lookup call, writing its result into the `as` slot. The `as` slot may be a\n * user-named field path (when the lookup is the whole RHS of an assignment /\n * `let`) or an internal `__jsmql.__lookupN` slot (when chained).\n */\nexport function lowerLookup(\n  call: LookupCall,\n  as: string,\n  outerCtx: GenerateCtx,\n  lowerBlock: SubPipelineLowerer,\n  enclosing: EnclosingLookupContext = EMPTY_ENCLOSING,\n): object[] {\n  const pred = translatePredicate(call, outerCtx, lowerBlock, enclosing);\n  // `$lookup.from` is a bare string for same-database joins (`$$$.<coll>`) and\n  // an object `{ db, coll }` for cross-database joins (`$$$$.<db>.<coll>`).\n  // The object shape is the Atlas Data Federation form \u2014 community-server\n  // MongoDB does not accept it; we still emit it because the surface lights\n  // up on Atlas Data Federation and the runtime error on community Mongo\n  // names the offending shape if a user runs it on the wrong deployment.\n  // See docs/specs/lookup-stage.md and the DEVLOG entry.\n  const from: string | { db: string; coll: string } =\n    call.db !== undefined ? { db: call.db, coll: call.collection } : call.collection;\n  const stages: object[] = [];\n  if (pred.kind === \"basic\") {\n    stages.push({ $lookup: { from, localField: pred.localField, foreignField: pred.foreignField, as } });\n  } else {\n    stages.push({ $lookup: { from, let: pred.letVars, pipeline: pred.pipeline, as } });\n  }\n  if (call.method === \"find\") {\n    // JS `.find()` returns scalar-or-null. Overwrite the slot with `$first`\n    // so the row is preserved on no match (slot becomes null) and the slot\n    // holds a single doc on any match \u2014 no row fan-out.\n    stages.push({ $set: { [as]: { $first: `$${as}` } } });\n  }\n  return stages;\n}\n\n// \u2500\u2500 Chained-terminal recognition + materialisation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Top-down walk of `expr`. At each sub-tree, recognise either a\n * directly-consumed lookup or a \"chained terminal\" (`<lookup>.length`,\n * `<lookup>.reduce(fn, init)`). For each recognised lookup, allocate a\n * fresh slot, emit the prologue stages (the lookup itself, plus any\n * chained transform), and substitute a `FieldRef(slot)` into the\n * returned expression so the surrounding stage's codegen runs over the\n * materialised result.\n *\n * Anything not recognised as a lookup pattern is left alone but\n * recursed into so a lookup buried in (say) an arithmetic operand still\n * materialises correctly.\n *\n * Nested lookups inside an expression-body predicate of an outer lookup\n * materialise through the same recursive descent (with\n * `EnclosingLookupContext` threading), landing as prologue `$lookup`\n * stages inside the outer's `$lookup.pipeline`. Block-body nested\n * lookups are still rejected \u2014 see [DEF-023] in `translatePredicate`.\n */\nexport function extractLookupCalls(\n  expr: Expr,\n  outerCtx: GenerateCtx,\n  allocSlot: SlotAllocator,\n  lowerBlock: SubPipelineLowerer,\n  enclosing: EnclosingLookupContext = EMPTY_ENCLOSING,\n): { stages: object[]; rewritten: Expr } {\n  // Malformed-shape pre-check: if expr is a MethodCall on a DatabaseRef-rooted\n  // receiver, run the targeted validator so wrong-method (`fnid`), wrong-arity,\n  // and non-arrow-arg cases surface their precise messages instead of falling\n  // through to the generic \"must be followed by .find/.filter\" codegen error.\n  validateLookupShape(expr);\n  // Chained `.length` on a lookup\n  if (expr.type === \"MemberAccess\" && expr.member === \"length\") {\n    const innerCall = detectLookupCall(expr.object, outerCtx);\n    if (innerCall !== null) {\n      if (innerCall.method === \"find\") {\n        // `.find()` returns scalar-or-null (after `$set $first`); `.length` on\n        // a doc/null isn't meaningful and `$size` on a non-array would error\n        // at runtime. Mirror the `.find().reduce()` rejection with an\n        // actionable hint at the right call.\n        throw new CodegenError(\n          `.length on a .find() result is not meaningful \u2014 .find returns scalar-or-null. ` +\n            `Use .filter(...).length to count matching documents, or chain a field access ` +\n            `(.find(...).<field>) to read a property of the matched doc.`,\n          expr.pos,\n        );\n      }\n      const slot = allocSlot();\n      const stages = lowerLookup(innerCall, slot, outerCtx, lowerBlock, enclosing);\n      // .filter result is an array; $size is the array length.\n      stages.push({ $set: { [slot]: { $size: `$${slot}` } } });\n      return { stages, rewritten: { type: \"FieldRef\", path: slot, pos: expr.pos } };\n    }\n  }\n  // Chained `.reduce(fn, init)` on a lookup\n  if (expr.type === \"MethodCall\" && expr.method === \"reduce\") {\n    const innerCall = detectLookupCall(expr.object, outerCtx);\n    if (innerCall !== null) {\n      if (innerCall.method === \"find\") {\n        throw new CodegenError(\n          `.reduce() on a .find() result is not meaningful \u2014 .find returns a scalar-or-null. ` +\n            `Use .filter(...) before .reduce(), or read the scalar directly.`,\n          expr.pos,\n        );\n      }\n      // The reduce lambda runs over an array (the filter result). Hand off to\n      // the existing `.reduce` codegen by emitting a generic $set whose value\n      // is the reduce expression over the materialised slot.\n      const slot = allocSlot();\n      const stages = lowerLookup(innerCall, slot, outerCtx, lowerBlock, enclosing);\n      // Synthesize: `$set { slot: <reduceMethodCall over FieldRef(slot)> }`\n      const reduceCall: MethodCall = {\n        type: \"MethodCall\",\n        object: { type: \"FieldRef\", path: slot, pos: expr.pos },\n        method: \"reduce\",\n        args: expr.args,\n        pos: expr.pos,\n      };\n      const reduceExpr = generateWithCtx(reduceCall, outerCtx);\n      stages.push({ $set: { [slot]: reduceExpr } });\n      return { stages, rewritten: { type: \"FieldRef\", path: slot, pos: expr.pos } };\n    }\n  }\n  // Direct lookup as the whole expression\n  const direct = detectLookupCall(expr, outerCtx);\n  if (direct !== null) {\n    const slot = allocSlot();\n    const stages = lowerLookup(direct, slot, outerCtx, lowerBlock, enclosing);\n    return { stages, rewritten: { type: \"FieldRef\", path: slot, pos: expr.pos } };\n  }\n  // Chained stream methods on a `.filter` lookup (e.g.,\n  // `$$$.coll.filter(p).map(...).toSorted((a,b) => \u2026).slice(0, N)`): push the\n  // chain stages INTO the `$lookup.pipeline` body so methods without a clean\n  // expression-form ($sort with comparator, $unwind, $group, \u2026) lower the\n  // same way they would in a stage-position chain. The slot then holds the\n  // already-transformed array, and chained terminals (`.length`, `.reduce`)\n  // / member access on the result keep working through the recursion below.\n  const chained = tryExtractChainedLookup(expr, outerCtx, allocSlot, lowerBlock, enclosing);\n  if (chained !== null) return chained;\n  // Otherwise: recurse into children so a lookup buried deeper still\n  // materialises. Reuse the AST-mapping pattern but accumulate stages.\n  return descendAndExtract(expr, outerCtx, allocSlot, lowerBlock, enclosing);\n}\n\n/**\n * Detect `$$$.<coll>.filter(p).<m1>(...).<m2>(...)\u2026` \u2014 a `.filter` lookup\n * followed by one or more registered stream methods. When matched, build the\n * `$lookup` with all the chain stages pushed into its `pipeline:` body and\n * return a `FieldRef(slot)` substituting the entire chain. The slot holds the\n * transformed array; the surrounding expression's codegen reads it as\n * `\"$<slot>\"`.\n *\n * Returns `null` when:\n *   - `expr` isn't a `MethodCall`,\n *   - the chain has no methods on top of the lookup head,\n *   - the innermost receiver isn't a `.filter` lookup (`.find` heads are\n *     scalar \u2014 chain methods don't apply the same way; left to the caller's\n *     existing `descendAndExtract` path), or\n *   - any chain method isn't in the stream-methods registry.\n *\n * This is the stage-form counterpart to the expression-form fallthrough\n * `descendAndExtract` would produce: same final array, fewer stages, and\n * stream-method semantics for `.toSorted` / `.toReversed` / `.flatMap` /\n * `.slice` / `.concat` / `.map` / `.filter` (which expression-form either\n * couldn't represent or represented as the bulkier `$map` / `$filter` / `$slice`\n * operators).\n */\nfunction tryExtractChainedLookup(\n  expr: Expr,\n  outerCtx: GenerateCtx,\n  allocSlot: SlotAllocator,\n  lowerBlock: SubPipelineLowerer,\n  enclosing: EnclosingLookupContext = EMPTY_ENCLOSING,\n): { stages: object[]; rewritten: Expr } | null {\n  if (expr.type !== \"MethodCall\") return null;\n  // Walk back collecting the chain of MethodCall nodes.\n  const methods: MethodCall[] = [];\n  let cur: Expr = expr;\n  while (cur.type === \"MethodCall\") {\n    methods.push(cur);\n    cur = cur.object;\n  }\n  methods.reverse(); // innermost first\n  if (methods.length < 2) return null;\n  // Innermost must be a `.filter` lookup head (a `$$$.<coll>.filter(<lambda>)` call).\n  const head = methods[0];\n  const direct = detectLookupCall(head, outerCtx);\n  if (direct === null) return null;\n  if (direct.method !== \"filter\") return null;\n  // Every subsequent method must come from the stream-methods registry \u2014\n  // otherwise the chain falls through to the existing expression-form path,\n  // which can still handle e.g. string methods on lookup results.\n  for (let i = 1; i < methods.length; i++) {\n    if (lookupStreamMethod(methods[i].method) === null) return null;\n  }\n  // Force pipeline form for the lookup so the chain stages can extend it.\n  // The enclosing context flows through so nested lookups inside the\n  // predicate materialise correctly with their own let-bindings.\n  const { letVars, pipelineBody } = buildPipelineFormPredicate(direct.lambda, outerCtx, lowerBlock, enclosing);\n  // Apply each chain method through the stream-methods registry. `inSubPipeline`\n  // is true so methods know they're emitting inside a sub-pipeline body.\n  const innerCtx = freshSubPipelineCtx(outerCtx);\n  for (let i = 1; i < methods.length; i++) {\n    const m = methods[i];\n    const def = lookupStreamMethod(m.method);\n    if (def === null) return null; // (defensive \u2014 already filtered above)\n    def.validate(m.args, m.pos);\n    const result = def.lower(m.args, innerCtx, m.pos, lowerBlock, pipelineBody, allocSlot, true);\n    if (result.replacesPreviousStage) pipelineBody.pop();\n    pipelineBody.push(...result.stages);\n  }\n  // Build the $lookup stage. `as` is an internal slot; the surrounding\n  // expression's codegen reads it. (Future optimisation: detect when the\n  // chain is the entire RHS of a `$.<field> = <chain>` and use the field\n  // path as `as` directly, dropping the trailing `$set` + `$unset`.)\n  const slot = allocSlot();\n  const from: string | { db: string; coll: string } =\n    direct.db !== undefined ? { db: direct.db, coll: direct.collection } : direct.collection;\n  return {\n    stages: [{ $lookup: { from, let: letVars, pipeline: pipelineBody, as: slot } }],\n    rewritten: { type: \"FieldRef\", path: slot, pos: expr.pos },\n  };\n}\n\nfunction descendAndExtract(\n  expr: Expr,\n  outerCtx: GenerateCtx,\n  allocSlot: SlotAllocator,\n  lowerBlock: SubPipelineLowerer,\n  enclosing: EnclosingLookupContext = EMPTY_ENCLOSING,\n): { stages: object[]; rewritten: Expr } {\n  const stages: object[] = [];\n  const rewriteChild = (child: Expr): Expr => {\n    const r = extractLookupCalls(child, outerCtx, allocSlot, lowerBlock, enclosing);\n    for (const s of r.stages) stages.push(s);\n    return r.rewritten;\n  };\n  switch (expr.type) {\n    case \"FieldRef\":\n    case \"CollectionRef\":\n    case \"DatabaseRef\":\n    case \"ClusterRef\":\n    case \"NumberLiteral\":\n    case \"BigIntLiteral\":\n    case \"StringLiteral\":\n    case \"BooleanLiteral\":\n    case \"NullLiteral\":\n    case \"UndefinedLiteral\":\n    case \"RegexLiteral\":\n    case \"ParamRef\":\n    case \"TypeCastRef\":\n    case \"MathConst\":\n    case \"MathCallRef\":\n    case \"DateNow\":\n      return { stages, rewritten: expr };\n    case \"BinaryExpr\":\n      return {\n        stages,\n        rewritten: {\n          type: \"BinaryExpr\",\n          op: expr.op,\n          left: rewriteChild(expr.left),\n          right: rewriteChild(expr.right),\n          pos: expr.pos,\n        },\n      };\n    case \"UnaryExpr\":\n      return {\n        stages,\n        rewritten: { type: \"UnaryExpr\", op: expr.op, operand: rewriteChild(expr.operand), pos: expr.pos },\n      };\n    case \"TernaryExpr\":\n      return {\n        stages,\n        rewritten: {\n          type: \"TernaryExpr\",\n          condition: rewriteChild(expr.condition),\n          consequent: rewriteChild(expr.consequent),\n          alternate: rewriteChild(expr.alternate),\n          pos: expr.pos,\n        },\n      };\n    case \"MemberAccess\":\n      return {\n        stages,\n        rewritten: {\n          type: \"MemberAccess\",\n          object: rewriteChild(expr.object),\n          member: expr.member,\n          pos: expr.pos,\n          ...(expr.optional && { optional: true }),\n        },\n      };\n    case \"IndexAccess\":\n      return {\n        stages,\n        rewritten: {\n          type: \"IndexAccess\",\n          object: rewriteChild(expr.object),\n          index: rewriteChild(expr.index),\n          pos: expr.pos,\n          ...(expr.optional && { optional: true }),\n        },\n      };\n    case \"MethodCall\":\n      return {\n        stages,\n        rewritten: {\n          type: \"MethodCall\",\n          object: rewriteChild(expr.object),\n          method: expr.method,\n          args: rewriteCallArgs(expr.args, rewriteChild),\n          pos: expr.pos,\n          ...(expr.optional && { optional: true }),\n        },\n      };\n    case \"CallExpression\":\n      return {\n        stages,\n        rewritten: {\n          type: \"CallExpression\",\n          callee: rewriteChild(expr.callee),\n          args: rewriteCallArgs(expr.args, rewriteChild),\n          pos: expr.pos,\n        },\n      };\n    case \"OperatorCall\":\n      return {\n        stages,\n        rewritten: {\n          type: \"OperatorCall\",\n          name: expr.name,\n          style: expr.style,\n          args: rewriteCallArgs(expr.args, rewriteChild),\n          pos: expr.pos,\n        },\n      };\n    case \"Lambda\":\n      // Lookups inside a lambda body (other than the lookup-callback lambda\n      // itself, which is already detected above) are uncommon and would only\n      // arise from very contrived nesting. Pass through \u2014 the codegen errors\n      // if a DatabaseRef escapes unhandled.\n      return { stages, rewritten: expr };\n    case \"ArrayLiteral\":\n      return {\n        stages,\n        rewritten: {\n          type: \"ArrayLiteral\",\n          elements: expr.elements.map((el): ArrayElement => {\n            if (el.type === \"SpreadElement\")\n              return { type: \"SpreadElement\", argument: rewriteChild(el.argument), pos: el.pos };\n            if (el.type === \"AssignExpr\")\n              return {\n                type: \"AssignExpr\",\n                target: rewriteChild(el.target),\n                value: rewriteChild(el.value),\n                pos: el.pos,\n              };\n            if (el.type === \"DeleteStmt\") return { type: \"DeleteStmt\", target: rewriteChild(el.target), pos: el.pos };\n            if (el.type === \"LetDecl\")\n              return { type: \"LetDecl\", name: el.name, value: rewriteChild(el.value), pos: el.pos };\n            return rewriteChild(el as Expr);\n          }),\n          pos: expr.pos,\n        },\n      };\n    case \"ObjectLiteral\":\n      return {\n        stages,\n        rewritten: {\n          type: \"ObjectLiteral\",\n          entries: expr.entries.map((entry): ObjectEntry => {\n            if (entry.type === \"SpreadElement\")\n              return { type: \"SpreadElement\", argument: rewriteChild(entry.argument), pos: entry.pos };\n            const kv: KeyValueEntry = {\n              type: \"KeyValueEntry\",\n              key: entry.key.kind === \"computed\" ? { kind: \"computed\", expr: rewriteChild(entry.key.expr) } : entry.key,\n              value: rewriteChild(entry.value),\n              pos: entry.pos,\n            };\n            return kv;\n          }),\n          pos: expr.pos,\n        },\n      };\n    case \"TemplateLiteral\":\n      return {\n        stages,\n        rewritten: {\n          type: \"TemplateLiteral\",\n          quasis: expr.quasis,\n          expressions: expr.expressions.map(rewriteChild),\n          pos: expr.pos,\n        },\n      };\n    case \"TypeofExpr\":\n      return { stages, rewritten: { type: \"TypeofExpr\", operand: rewriteChild(expr.operand), pos: expr.pos } };\n    case \"NewDate\":\n      return { stages, rewritten: { type: \"NewDate\", args: expr.args.map(rewriteChild), pos: expr.pos } };\n    case \"NewSet\":\n      return {\n        stages,\n        rewritten: { type: \"NewSet\", arg: expr.arg !== null ? rewriteChild(expr.arg) : null, pos: expr.pos },\n      };\n    case \"TypeCast\":\n      return { stages, rewritten: { type: \"TypeCast\", cast: expr.cast, arg: rewriteChild(expr.arg), pos: expr.pos } };\n    case \"MathCall\":\n      return {\n        stages,\n        rewritten: {\n          type: \"MathCall\",\n          method: expr.method,\n          args: rewriteCallArgs(expr.args, rewriteChild),\n          pos: expr.pos,\n        },\n      };\n    case \"ObjectCall\":\n      return {\n        stages,\n        rewritten: {\n          type: \"ObjectCall\",\n          method: expr.method,\n          args: rewriteCallArgs(expr.args, rewriteChild),\n          pos: expr.pos,\n        },\n      };\n    case \"ArrayFrom\":\n      return {\n        stages,\n        rewritten: {\n          type: \"ArrayFrom\",\n          input: rewriteChild(expr.input),\n          mapFn: expr.mapFn !== null ? rewriteChild(expr.mapFn) : null,\n          pos: expr.pos,\n        },\n      };\n    case \"NumberStatic\":\n      return {\n        stages,\n        rewritten: { type: \"NumberStatic\", method: expr.method, arg: rewriteChild(expr.arg), pos: expr.pos },\n      };\n    case \"DateUTC\":\n      return { stages, rewritten: { type: \"DateUTC\", args: expr.args.map(rewriteChild), pos: expr.pos } };\n  }\n}\n\nfunction rewriteCallArgs(args: CallArg[], rewrite: (e: Expr) => Expr): CallArg[] {\n  return args.map((a): CallArg => {\n    if (a.type === \"SpreadElement\") return { type: \"SpreadElement\", argument: rewrite(a.argument), pos: a.pos };\n    return rewrite(a);\n  });\n}\n", "// Facet translation: lowers `$ = { k1: $$.filter(p1), k2: $$.filter(p2), \u2026 }`\n// into a `$facet` aggregation stage.\n//\n// The user pattern: an object-literal RHS of `$ = \u2026` where every value is a\n// `$$.filter(<predicate>)` call. Each entry's predicate lambda becomes the\n// sub-pipeline body for that facet key:\n//\n//   $ = {\n//     topByScore: $$.filter(o => { $sort({ score: -1 }); $limit(10); }),\n//     recent:     $$.filter(o => o.createdAt >= new Date(\"2026-01-01\")),\n//     byStatus:   $$.filter(o => { $group({ _id: o.status, n: $sum(1) }); }),\n//   };\n//\n//   \u2192 [{ $facet: {\n//         topByScore: [{ $sort: { score: -1 } }, { $limit: 10 }],\n//         recent:     [{ $match: { createdAt: { $gte: <Date> } } }],\n//         byStatus:   [{ $group: { _id: \"$status\", n: { $sum: 1 } } }]\n//       } }]\n//\n// Sister to lookup-translation (which handles `$$$.<coll>.find/filter` \u2192\n// `$lookup`) and union-translation (which handles `$$.push` \u2192 `$unionWith`).\n// All three lower their predicate lambda through `lowerLambdaPredicate` (shared\n// from lookup-translation); facet's twist is rejecting any `$.<field>`\n// reference, because inside a facet sub-pipeline the lambda param IS the current\n// document \u2014 there's no separate outer-doc concept.\n\nimport type { Expr } from \"./ast.ts\";\nimport { CodegenError, freshFacetCtx, type GenerateCtx } from \"./codegen.ts\";\nimport { lowerLambdaPredicate, type SubPipelineLowerer } from \"./lookup-translation.ts\";\n\ntype LambdaNode = Extract<Expr, { type: \"Lambda\" }>;\n\nexport type FacetEntry = { key: string; lambda: LambdaNode; pos: number };\n\n/**\n * Recognise an object-literal RHS where every value is a `$$.filter(<lambda>)`.\n * Returns the parsed facets, or `null` when no entry has the filter shape (so\n * the caller falls back to `$replaceWith`).\n *\n * If *any* entry is a `$$.filter(...)` but others are not, throws a precise\n * mixed-shape error \u2014 the user clearly meant a facet, so silently falling\n * through to `$replaceWith` would surface a confusing \"$$ is statement-only\"\n * downstream.\n */\nexport function detectFacetShape(value: Expr): FacetEntry[] | null {\n  if (value.type !== \"ObjectLiteral\") return null;\n  if (value.entries.length === 0) return null;\n\n  let hasFilter = false;\n  for (const entry of value.entries) {\n    if (entry.type !== \"KeyValueEntry\") continue;\n    if (asCollectionFilterLambda(entry.value) !== null) {\n      hasFilter = true;\n      break;\n    }\n  }\n  if (!hasFilter) return null;\n\n  const facets: FacetEntry[] = [];\n  for (const entry of value.entries) {\n    if (entry.type !== \"KeyValueEntry\") {\n      throw new CodegenError(\n        `\\`$ = { ... }\\` $facet pattern: spread entries are not allowed. Every value must be \\`$$.filter(<predicate>)\\`.`,\n        entry.pos,\n      );\n    }\n    if (entry.key.kind !== \"static\") {\n      throw new CodegenError(\n        `\\`$ = { ... }\\` $facet pattern: computed keys are not allowed. Facet names are stage output keys and must be static identifiers.`,\n        entry.pos,\n      );\n    }\n    const lambda = asCollectionFilterLambda(entry.value);\n    if (lambda === null) {\n      throw new CodegenError(\n        `\\`$ = { ... }\\` $facet pattern: every value must be \\`$$.filter(<predicate>)\\`. Entry '${entry.key.name}' is something else. Either convert it to \\`$$.filter(<predicate>)\\` or move it out of the object.`,\n        entry.value.pos,\n      );\n    }\n    facets.push({ key: entry.key.name, lambda, pos: entry.pos });\n  }\n  return facets;\n}\n\nfunction asCollectionFilterLambda(expr: Expr): LambdaNode | null {\n  if (expr.type !== \"MethodCall\") return null;\n  if (expr.method !== \"filter\") return null;\n  if (expr.object.type !== \"CollectionRef\") return null;\n  if (expr.args.length !== 1) return null;\n  const arg = expr.args[0];\n  if (arg.type !== \"Lambda\") return null;\n  return arg as LambdaNode;\n}\n\n/**\n * Lower the detected facets to a single `$facet` stage. Each entry's lambda\n * becomes one sub-pipeline (one `$match` for expression-body predicates;\n * the block's stages for block-body predicates).\n */\nexport function lowerFacet(facets: FacetEntry[], outerCtx: GenerateCtx, lowerBlock: SubPipelineLowerer): object[] {\n  const body: Record<string, object[]> = {};\n  const seen = new Set<string>();\n  for (const f of facets) {\n    if (seen.has(f.key)) {\n      throw new CodegenError(\n        `\\`$ = { ... }\\` $facet pattern: duplicate key '${f.key}'. Facet names must be unique.`,\n        f.pos,\n      );\n    }\n    seen.add(f.key);\n    body[f.key] = lowerFacetEntry(f.lambda, outerCtx, lowerBlock);\n  }\n  return [{ $facet: body }];\n}\n\n/**\n * Translate one `$$.filter(<lambda>)` predicate into the sub-pipeline body\n * for its facet key. Requires exactly one lambda parameter \u2014 the user has\n * to name the doc explicitly (`o => \u2026`) so the rejection message for\n * `$.<field>` references can point at the right replacement (`o.<field>`).\n *\n * `$.<field>` references inside the predicate are rejected with an\n * actionable error: inside a facet sub-pipeline, the lambda param IS the\n * current document, so the two notations would mean the same thing \u2014 we\n * force one canonical spelling rather than supporting both.\n */\nfunction lowerFacetEntry(lambda: LambdaNode, outerCtx: GenerateCtx, lowerBlock: SubPipelineLowerer): object[] {\n  if (lambda.params.length !== 1) {\n    throw new CodegenError(\n      `\\`$$.filter(<predicate>)\\` inside \\`$ = { ... }\\` $facet must take exactly one parameter \u2014 write \\`$$.filter(o => \u2026)\\` (the param name is your choice). The param represents each input document inside the facet sub-pipeline.`,\n      lambda.pos,\n    );\n  }\n  // Shared expr-or-block predicate lowering (see `lowerLambdaPredicate`). Inside\n  // a facet sub-pipeline the lambda param IS the current document, so a\n  // `$.<field>` reference (captured as a non-empty `letVars`) is rejected in\n  // favour of the param spelling.\n  return lowerLambdaPredicate(lambda, outerCtx, lowerBlock, {\n    freshCtx: freshFacetCtx,\n    onLocalRef: rejectLocalRef,\n    missingBody: () => {\n      throw new CodegenError(\n        `\\`$$.filter(p)\\` lambda is missing a body \u2014 internal parser bug; please report.`,\n        lambda.pos,\n      );\n    },\n  });\n}\n\nfunction rejectLocalRef(letVars: Record<string, string>, param: string, pos: number): never {\n  const sample = Object.values(letVars)[0]; // e.g. \"$createdAt\"\n  const samplePath = sample.replace(/^\\$+/, \"\");\n  throw new CodegenError(\n    `\\`$.<field>\\` inside \\`$$.filter(p)\\` in a \\`$ = { ... }\\` $facet is not supported \u2014 use the lambda parameter (e.g. \\`${param}.${samplePath}\\`) to reference the current document. Inside a facet sub-pipeline, the lambda param IS the current document; \\`$.<field>\\` would mean the same thing and adding a second spelling for it would only invite drift.`,\n    pos,\n  );\n}\n", "// Per-stage body validation.\n//\n// Catches stage-body violations the MongoDB server always rejects, regardless\n// of data or deployment \u2014 wrong literal types, out-of-range literal numbers,\n// bad enum values, missing required keys, mutually-exclusive keys, malformed\n// literal arrays, illegal field-name formats. The structural *placement* rules\n// (must-be-first / must-be-last / forbidden-in-sub-pipeline) live in\n// pipeline.ts; this module owns the *shape* of a single stage body.\n//\n// THE LITERAL-GATING INVARIANT: every check inspects only fully-static literal\n// shapes. The moment the checked slot holds a field reference, an expression, an\n// operator call, a template literal, a computed key, or a spread, the check is a\n// no-op and the MQL is emitted unchanged. We never throw on a value we cannot\n// statically pin down \u2014 a *probable* violation must still compile (rule #2).\n// This is how comprehensive coverage coexists with \"only 100%-certain throws\".\n//\n// Validators see only USER-written stage bodies: sugar-generated stages\n// ($lookup from `$$$.coll.find`, $unionWith from `$$.push`, \u2026) build their\n// objects directly and never pass through `generateStageBody`.\n//\n// See docs/specs/pipeline-validation.md.\n\nimport type { Expr } from \"./ast.ts\";\nimport { CodegenError } from \"./codegen.ts\";\nimport { closestNameTo } from \"./levenshtein.ts\";\n\n// \u2500\u2500 Literal-inspection helpers (the gate) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** The numeric value of `e` IF it is a literal number (incl. a unary `-` on one), else null. */\nfunction litNumber(e: Expr): number | null {\n  if (e.type === \"NumberLiteral\") return e.value;\n  if (e.type === \"UnaryExpr\" && e.op === \"-\" && e.operand.type === \"NumberLiteral\") return -e.operand.value;\n  return null;\n}\n\n/** The string value of `e` IF it is a literal string, else null. */\nfunction litString(e: Expr): string | null {\n  return e.type === \"StringLiteral\" ? e.value : null;\n}\n\n/** The boolean value of `e` IF it is a literal boolean, else null. */\nfunction litBool(e: Expr): boolean | null {\n  return e.type === \"BooleanLiteral\" ? e.value : null;\n}\n\n/**\n * A human description IF `e` is a fully-static literal (scalar / array / object /\n * regex), else null \u2014 null means \"a non-literal expression we can't judge\".\n * Note: a negative number literal is a `UnaryExpr`, so it is NOT described here;\n * use `litNumber` for numeric slots.\n */\nfunction describeLiteral(e: Expr): string | null {\n  switch (e.type) {\n    case \"NumberLiteral\":\n      return \"a number\";\n    case \"BigIntLiteral\":\n      return \"a bigint\";\n    case \"StringLiteral\":\n      return \"a string\";\n    case \"BooleanLiteral\":\n      return \"a boolean\";\n    case \"NullLiteral\":\n      return \"null\";\n    case \"ArrayLiteral\":\n      return \"an array\";\n    case \"ObjectLiteral\":\n      return \"an object\";\n    case \"RegexLiteral\":\n      return \"a regular expression\";\n    default:\n      return null;\n  }\n}\n\ntype ObjectInfo = { byKey: Map<string, Expr>; hasSpread: boolean };\n\n/**\n * Static view of an object-literal body: its static keys \u2192 value, plus whether\n * a spread is present. Returns null when `e` is not an object literal OR has a\n * computed key \u2014 in both cases we can't reason statically, so callers no-op.\n */\nfunction objectInfo(e: Expr): ObjectInfo | null {\n  if (e.type !== \"ObjectLiteral\") return null;\n  const byKey = new Map<string, Expr>();\n  let hasSpread = false;\n  for (const entry of e.entries) {\n    if (entry.type === \"SpreadElement\") {\n      hasSpread = true;\n      continue;\n    }\n    if (entry.key.kind !== \"static\") return null;\n    byKey.set(entry.key.name, entry.value);\n  }\n  return { byKey, hasSpread };\n}\n\n/** Literal elements of an array literal, or null if `e` isn't an array literal. */\nfunction arrayElements(e: Expr): Expr[] | null {\n  if (e.type !== \"ArrayLiteral\") return null;\n  const out: Expr[] = [];\n  for (const el of e.elements) {\n    // A spread / assignment inside the array \u2192 not a plain value list; bail.\n    if (el.type === \"SpreadElement\" || el.type === \"AssignExpr\" || el.type === \"DeleteStmt\" || el.type === \"LetDecl\") {\n      return null;\n    }\n    out.push(el);\n  }\n  return out;\n}\n\n// \u2500\u2500 Shared check helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Require `keys` to be present on an object-literal body (skips if a spread hides them). */\nfunction requireKeys(stage: string, info: ObjectInfo, bodyPos: number, keys: readonly string[]): void {\n  if (info.hasSpread) return;\n  for (const k of keys) {\n    if (!info.byKey.has(k)) {\n      throw new CodegenError(`'${stage}' requires the '${k}' field, but it is missing.`, bodyPos);\n    }\n  }\n}\n\n/**\n * Open an object-body validator: return the body's key map, or `null` when the\n * body isn't an inspectable object literal (validation is best-effort \u2014 a field\n * path or runtime expression in body position is left for MongoDB to check), in\n * which case the caller `return`s. Any `required` keys are enforced up front.\n * Folds the `objectInfo` + null-gate + `requireKeys` prelude that opens most\n * object-shaped stage validators into one call.\n */\nfunction requireObjectBody(stage: string, body: Expr, required: readonly string[] = []): ObjectInfo | null {\n  const info = objectInfo(body);\n  if (info === null) return null;\n  requireKeys(stage, info, body.pos, required);\n  return info;\n}\n\n/** Throw if a literal-string slot value is outside the allowed enum (with a \"Did you mean\"). */\nfunction checkEnum(stage: string, field: string, value: Expr, allowed: readonly string[]): void {\n  const s = litString(value);\n  if (s === null || allowed.includes(s)) return;\n  const near = closestNameTo(s, allowed);\n  const hint = near !== null ? ` Did you mean '${near}'?` : \"\";\n  throw new CodegenError(`'${stage}' ${field} must be one of: ${allowed.join(\", \")} \u2014 got '${s}'.${hint}`, value.pos);\n}\n\n/** Throw if a numeric slot holds a definitely-wrong literal (non-number, non-integer, or out of bound). */\nfunction checkIntBound(stage: string, body: Expr, opts: { min: number; label: string }): void {\n  const n = litNumber(body);\n  if (n === null) {\n    const desc = describeLiteral(body);\n    // Only a literal of a clearly-wrong type throws; a field/expression is fine.\n    if (desc !== null) {\n      throw new CodegenError(`'${stage}' expects an integer, but got ${desc}.`, body.pos);\n    }\n    return;\n  }\n  if (!Number.isInteger(n)) {\n    throw new CodegenError(`'${stage}' must be an integer, but got ${n}.`, body.pos);\n  }\n  if (n < opts.min) {\n    throw new CodegenError(`'${stage}' must be ${opts.label}, but got ${n}.`, body.pos);\n  }\n}\n\n/** Reject a literal-scalar new-root (a document is required). */\nfunction rejectNonDocumentNewRoot(stage: string, value: Expr): void {\n  const desc = describeLiteral(value);\n  // A literal object is a valid document; everything else literal is not.\n  if (desc !== null && value.type !== \"ObjectLiteral\") {\n    throw new CodegenError(\n      `'${stage}' must resolve to a document, but got ${desc}. ` + `Wrap it, e.g. '{ value: \u2026 }'.`,\n      value.pos,\n    );\n  }\n}\n\n// \u2500\u2500 $match query-operator placement \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// A raw `$match` object body passes through verbatim, so query operators are\n// reachable. Some have positional / availability rules the server enforces:\n//   - `$text` may only appear in a `$match` that is the pipeline's FIRST stage.\n//   - `$near` / `$nearSphere` / `$where` are not allowed in an aggregation\n//     `$match` at all (use `$geoNear` / `$geoWithin` / `$expr` instead).\n// We walk the (static) match body for these keys, recursing through nested\n// field-value objects and `$and`/`$or`/`$nor` arrays.\n\nconst MATCH_DISALLOWED: Record<string, string> = {\n  $near: \"use the '$geoNear' stage (it must be the first stage), or '$geoWithin' with '$center'/'$centerSphere'\",\n  $nearSphere: \"use the '$geoNear' stage (it must be the first stage), or '$geoWithin' with '$centerSphere'\",\n  $where: \"use '$expr' with a query expression (or '$function' for server-side JS)\",\n};\n\n/** First occurrence of any `names` key in a (static) `$match` body, recursing into objects/arrays. */\nfunction findMatchOperator(body: Expr, names: ReadonlySet<string>): { name: string; pos: number } | null {\n  if (body.type === \"ObjectLiteral\") {\n    for (const entry of body.entries) {\n      if (entry.type !== \"KeyValueEntry\") continue;\n      if (entry.key.kind === \"static\" && names.has(entry.key.name)) {\n        return { name: entry.key.name, pos: entry.pos };\n      }\n      const found = findMatchOperator(entry.value, names);\n      if (found !== null) return found;\n    }\n  } else if (body.type === \"ArrayLiteral\") {\n    for (const el of body.elements) {\n      if (\n        el.type === \"SpreadElement\" ||\n        el.type === \"AssignExpr\" ||\n        el.type === \"DeleteStmt\" ||\n        el.type === \"LetDecl\"\n      ) {\n        continue;\n      }\n      const found = findMatchOperator(el, names);\n      if (found !== null) return found;\n    }\n  }\n  return null;\n}\n\nconst DISALLOWED_SET: ReadonlySet<string> = new Set(Object.keys(MATCH_DISALLOWED));\nconst TEXT_SET: ReadonlySet<string> = new Set([\"$text\"]);\n\n/**\n * Enforce `$match` query-operator placement (only meaningful for a raw object\n * body \u2014 an expression body can't contain these). `isTopLevel`/`isFirstStage`\n * gate the `$text`-must-be-first rule; the disallowed-operator rule always fires.\n */\nexport function validateMatchPlacement(body: Expr, opts: { isTopLevel: boolean; isFirstStage: boolean }): void {\n  if (body.type !== \"ObjectLiteral\") return;\n  const disallowed = findMatchOperator(body, DISALLOWED_SET);\n  if (disallowed !== null) {\n    throw new CodegenError(\n      `'${disallowed.name}' is not allowed inside an aggregation '$match' \u2014 ${MATCH_DISALLOWED[disallowed.name]}.`,\n      disallowed.pos,\n    );\n  }\n  if (opts.isTopLevel && !opts.isFirstStage) {\n    const text = findMatchOperator(body, TEXT_SET);\n    if (text !== null) {\n      throw new CodegenError(\n        `A '$match' that uses '$text' must be the first stage in a pipeline. Move it to the front.`,\n        text.pos,\n      );\n    }\n  }\n}\n\n// \u2500\u2500 Per-stage validators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst MERGE_WHEN_MATCHED = [\"replace\", \"keepExisting\", \"merge\", \"fail\"] as const;\nconst MERGE_WHEN_NOT_MATCHED = [\"insert\", \"discard\", \"fail\"] as const;\nconst FILL_METHODS = [\"linear\", \"locf\"] as const;\nconst BUCKET_AUTO_GRANULARITY = [\n  \"R5\",\n  \"R10\",\n  \"R20\",\n  \"R40\",\n  \"R80\",\n  \"1-2-5\",\n  \"E6\",\n  \"E12\",\n  \"E24\",\n  \"E48\",\n  \"E96\",\n  \"E192\",\n  \"POWERSOF2\",\n] as const;\n\nfunction validateCount(body: Expr): void {\n  const s = litString(body);\n  if (s === null) {\n    const desc = describeLiteral(body);\n    if (desc !== null) throw new CodegenError(`'$count' expects a field-name string, but got ${desc}.`, body.pos);\n    return;\n  }\n  if (s.length === 0) throw new CodegenError(`'$count' field name must be a non-empty string.`, body.pos);\n  if (s.startsWith(\"$\")) throw new CodegenError(`'$count' field name cannot start with '$' (got '${s}').`, body.pos);\n  if (s.includes(\".\")) throw new CodegenError(`'$count' field name cannot contain '.' (got '${s}').`, body.pos);\n}\n\nfunction validateSort(body: Expr): void {\n  const info = requireObjectBody(\"$sort\", body);\n  if (info === null) return;\n  if (info.byKey.size > 32 && !info.hasSpread) {\n    throw new CodegenError(`'$sort' accepts at most 32 keys, but got ${info.byKey.size}.`, body.pos);\n  }\n  for (const [key, value] of info.byKey) {\n    const n = litNumber(value);\n    if (n !== null && n !== 1 && n !== -1) {\n      throw new CodegenError(\n        `'$sort' direction for '${key}' must be 1 (ascending) or -1 (descending), but got ${n}.`,\n        value.pos,\n      );\n    }\n    // SQL habit: `$sort({ createdAt: \"desc\" })` / `{ x: true }`. A literal\n    // string/bool direction is always wrong (the server takes only 1 / -1, or a\n    // `{ $meta: \u2026 }` object \u2014 which is not a literal, so it slips past the gate).\n    const str = litString(value);\n    const bool = litBool(value);\n    if (str !== null || bool !== null) {\n      const got = str !== null ? `'${str}'` : String(bool);\n      throw new CodegenError(\n        `'$sort' direction for '${key}' must be 1 (ascending) or -1 (descending), but got ${got}.`,\n        value.pos,\n      );\n    }\n  }\n}\n\nfunction validateProject(body: Expr): void {\n  const info = requireObjectBody(\"$project\", body);\n  if (info === null) return;\n  if (info.byKey.size === 0 && !info.hasSpread) {\n    throw new CodegenError(`'$project' specification must name at least one field.`, body.pos);\n  }\n  let includeKey: string | null = null;\n  let excludeKey: string | null = null;\n  for (const [key, value] of info.byKey) {\n    if (key === \"_id\") continue; // _id may be excluded in an inclusion projection\n    const n = litNumber(value);\n    const b = litBool(value);\n    if (n === 0 || b === false) excludeKey = key;\n    else if (n === 1 || b === true) includeKey = key;\n  }\n  if (includeKey !== null && excludeKey !== null) {\n    throw new CodegenError(\n      `'$project' cannot mix field inclusion ('${includeKey}: 1') and exclusion ('${excludeKey}: 0') \u2014 ` +\n        `only '_id' may be excluded in an inclusion projection. Use one mode: list fields to keep, or fields to drop.`,\n      body.pos,\n    );\n  }\n}\n\nfunction validateUnset(body: Expr): void {\n  const s = litString(body);\n  if (s !== null) {\n    if (s.length === 0) throw new CodegenError(`'$unset' field name must be a non-empty string.`, body.pos);\n    return;\n  }\n  const els = arrayElements(body);\n  if (els === null) return;\n  if (els.length === 0) throw new CodegenError(`'$unset' field-name array must not be empty.`, body.pos);\n  for (const el of els) {\n    if (litString(el) === null && describeLiteral(el) !== null) {\n      throw new CodegenError(`'$unset' field-name array must contain only strings.`, el.pos);\n    }\n  }\n}\n\nfunction validateUnwind(body: Expr): void {\n  const s = litString(body);\n  if (s !== null) {\n    if (!s.startsWith(\"$\")) {\n      throw new CodegenError(`'$unwind' path must be a field path starting with '$' (got '${s}').`, body.pos);\n    }\n    return;\n  }\n  const info = requireObjectBody(\"$unwind\", body);\n  if (info === null) return;\n  const path = info.byKey.get(\"path\");\n  if (path !== undefined) {\n    const ps = litString(path);\n    if (ps !== null && !ps.startsWith(\"$\")) {\n      throw new CodegenError(`'$unwind' path must be a field path starting with '$' (got '${ps}').`, path.pos);\n    }\n  }\n  const idx = info.byKey.get(\"includeArrayIndex\");\n  if (idx !== undefined) {\n    const is = litString(idx);\n    if (is !== null && is.startsWith(\"$\")) {\n      throw new CodegenError(`'$unwind' includeArrayIndex name cannot start with '$' (got '${is}').`, idx.pos);\n    }\n  }\n  const preserve = info.byKey.get(\"preserveNullAndEmptyArrays\");\n  if (preserve !== undefined && litBool(preserve) === null) {\n    const desc = describeLiteral(preserve);\n    if (desc !== null) {\n      throw new CodegenError(`'$unwind' preserveNullAndEmptyArrays must be a boolean, but got ${desc}.`, preserve.pos);\n    }\n  }\n}\n\nfunction validateSample(body: Expr): void {\n  const info = requireObjectBody(\"$sample\", body, [\"size\"]);\n  if (info === null) return;\n  const size = info.byKey.get(\"size\");\n  if (size !== undefined) checkIntBound(\"$sample size\", size, { min: 0, label: \"a non-negative integer\" });\n}\n\nfunction validateBucket(body: Expr): void {\n  const info = requireObjectBody(\"$bucket\", body, [\"groupBy\", \"boundaries\"]);\n  if (info === null) return;\n  const boundaries = info.byKey.get(\"boundaries\");\n  if (boundaries === undefined) return;\n  const els = arrayElements(boundaries);\n  if (els === null) return;\n  if (els.length < 2) {\n    throw new CodegenError(`'$bucket' boundaries must list at least 2 values, but got ${els.length}.`, boundaries.pos);\n  }\n  // Strictly-ascending + same-type checks only for an all-literal numeric or string array.\n  const nums = els.map(litNumber);\n  if (nums.every((n) => n !== null)) {\n    for (let i = 1; i < nums.length; i++) {\n      if ((nums[i] as number) <= (nums[i - 1] as number)) {\n        throw new CodegenError(\n          `'$bucket' boundaries must be in strictly ascending order (${nums[i - 1]} is not < ${nums[i]}).`,\n          boundaries.pos,\n        );\n      }\n    }\n    return;\n  }\n  const strs = els.map(litString);\n  if (strs.every((s) => s !== null)) {\n    for (let i = 1; i < strs.length; i++) {\n      if ((strs[i] as string) <= (strs[i - 1] as string)) {\n        throw new CodegenError(`'$bucket' boundaries must be in strictly ascending order.`, boundaries.pos);\n      }\n    }\n    return;\n  }\n  // A mix of literal numbers and literal strings is a type error.\n  const allLiteral = els.every((e) => describeLiteral(e) !== null);\n  if (allLiteral && (nums.some((n) => n !== null) || strs.some((s) => s !== null))) {\n    const mixed = nums.some((n) => n !== null) && strs.some((s) => s !== null);\n    if (mixed) {\n      throw new CodegenError(`'$bucket' boundaries must all be the same type.`, boundaries.pos);\n    }\n  }\n}\n\nfunction validateBucketAuto(body: Expr): void {\n  const info = requireObjectBody(\"$bucketAuto\", body, [\"groupBy\", \"buckets\"]);\n  if (info === null) return;\n  const buckets = info.byKey.get(\"buckets\");\n  if (buckets !== undefined) checkIntBound(\"$bucketAuto buckets\", buckets, { min: 1, label: \"a positive integer\" });\n  const granularity = info.byKey.get(\"granularity\");\n  if (granularity !== undefined) checkEnum(\"$bucketAuto\", \"granularity\", granularity, BUCKET_AUTO_GRANULARITY);\n}\n\nfunction validateSetWindowFields(body: Expr): void {\n  const info = requireObjectBody(\"$setWindowFields\", body, [\"output\"]);\n  if (info === null) return;\n  const output = info.byKey.get(\"output\");\n  if (output === undefined) return;\n  const outInfo = objectInfo(output);\n  if (outInfo === null) return;\n  for (const [, fieldSpec] of outInfo.byKey) {\n    const specInfo = objectInfo(fieldSpec);\n    if (specInfo === null) continue;\n    const window = specInfo.byKey.get(\"window\");\n    if (window === undefined) continue;\n    const winInfo = objectInfo(window);\n    if (winInfo === null) continue;\n    if (winInfo.byKey.has(\"documents\") && winInfo.byKey.has(\"range\")) {\n      throw new CodegenError(\n        `'$setWindowFields' window cannot specify both 'documents' and 'range' \u2014 they are mutually exclusive.`,\n        window.pos,\n      );\n    }\n  }\n}\n\nfunction validateFill(body: Expr): void {\n  const info = requireObjectBody(\"$fill\", body, [\"output\"]);\n  if (info === null) return;\n  const output = info.byKey.get(\"output\");\n  if (output === undefined) return;\n  const outInfo = objectInfo(output);\n  if (outInfo === null) return;\n  let needsSortBy = false;\n  for (const [field, fieldSpec] of outInfo.byKey) {\n    const specInfo = objectInfo(fieldSpec);\n    if (specInfo === null) continue;\n    const hasValue = specInfo.byKey.has(\"value\");\n    const method = specInfo.byKey.get(\"method\");\n    if (hasValue && method !== undefined) {\n      throw new CodegenError(\n        `'$fill' output field '${field}' cannot specify both 'value' and 'method' \u2014 they are mutually exclusive.`,\n        fieldSpec.pos,\n      );\n    }\n    if (method !== undefined) {\n      checkEnum(\"$fill\", `output field '${field}' method`, method, FILL_METHODS);\n      const ms = litString(method);\n      if (ms === \"linear\" || ms === \"locf\") needsSortBy = true;\n    }\n  }\n  if (needsSortBy && !info.hasSpread && !info.byKey.has(\"sortBy\")) {\n    throw new CodegenError(\n      `'$fill' requires 'sortBy' when an output field uses the 'linear' or 'locf' method.`,\n      body.pos,\n    );\n  }\n}\n\nfunction validateGraphLookup(body: Expr): void {\n  const info = requireObjectBody(\"$graphLookup\", body, [\n    \"from\",\n    \"startWith\",\n    \"connectFromField\",\n    \"connectToField\",\n    \"as\",\n  ]);\n  if (info === null) return;\n  const maxDepth = info.byKey.get(\"maxDepth\");\n  if (maxDepth !== undefined)\n    checkIntBound(\"$graphLookup maxDepth\", maxDepth, { min: 0, label: \"a non-negative integer\" });\n}\n\nfunction validateMerge(body: Expr): void {\n  const info = requireObjectBody(\"$merge\", body, [\"into\"]); // string form (\"coll\") returns null \u2192 fine\n  if (info === null) return;\n  const whenMatched = info.byKey.get(\"whenMatched\");\n  // whenMatched may be a pipeline (array) \u2014 only the string form is enum-checked.\n  if (whenMatched !== undefined && litString(whenMatched) !== null) {\n    checkEnum(\"$merge\", \"whenMatched\", whenMatched, MERGE_WHEN_MATCHED);\n  }\n  const whenNotMatched = info.byKey.get(\"whenNotMatched\");\n  if (whenNotMatched !== undefined) checkEnum(\"$merge\", \"whenNotMatched\", whenNotMatched, MERGE_WHEN_NOT_MATCHED);\n}\n\nfunction validateLookup(body: Expr): void {\n  requireObjectBody(\"$lookup\", body, [\"from\", \"as\"]);\n}\n\nfunction validateUnionWith(body: Expr): void {\n  const info = requireObjectBody(\"$unionWith\", body); // string form (\"coll\") returns null \u2192 fine\n  if (info === null) return;\n  if (info.hasSpread) return;\n  if (!info.byKey.has(\"coll\") && !info.byKey.has(\"pipeline\")) {\n    throw new CodegenError(`'$unionWith' requires a 'coll' and/or a 'pipeline'.`, body.pos);\n  }\n}\n\nfunction validateReplaceRoot(body: Expr): void {\n  const info = requireObjectBody(\"$replaceRoot\", body, [\"newRoot\"]);\n  if (info === null) return;\n  const newRoot = info.byKey.get(\"newRoot\");\n  if (newRoot !== undefined) rejectNonDocumentNewRoot(\"$replaceRoot newRoot\", newRoot);\n}\n\nfunction validateGroup(body: Expr): void {\n  requireObjectBody(\"$group\", body, [\"_id\"]);\n}\n\nfunction validateGeoNear(body: Expr): void {\n  requireObjectBody(\"$geoNear\", body, [\"near\"]);\n}\n\nfunction validateDocuments(body: Expr): void {\n  if (body.type === \"ArrayLiteral\") return;\n  const desc = describeLiteral(body);\n  if (desc !== null) {\n    throw new CodegenError(`'$documents' expects an array of documents, but got ${desc}.`, body.pos);\n  }\n}\n\ntype BodyValidator = (body: Expr) => void;\n\nconst STAGE_BODY_VALIDATORS: Record<string, BodyValidator> = {\n  $limit: (b) => checkIntBound(\"$limit\", b, { min: 1, label: \"a positive integer\" }),\n  $skip: (b) => checkIntBound(\"$skip\", b, { min: 0, label: \"a non-negative integer\" }),\n  $sample: validateSample,\n  $count: validateCount,\n  $sort: validateSort,\n  $project: validateProject,\n  $unset: validateUnset,\n  $unwind: validateUnwind,\n  $bucket: validateBucket,\n  $bucketAuto: validateBucketAuto,\n  $setWindowFields: validateSetWindowFields,\n  $fill: validateFill,\n  $group: validateGroup,\n  $lookup: validateLookup,\n  $unionWith: validateUnionWith,\n  $graphLookup: validateGraphLookup,\n  $merge: validateMerge,\n  $replaceRoot: validateReplaceRoot,\n  $replaceWith: (b) => rejectNonDocumentNewRoot(\"$replaceWith\", b),\n  $geoNear: validateGeoNear,\n  $documents: validateDocuments,\n};\n\n/**\n * Validate a stage's body against the 100%-static-certain shape rules. A no-op\n * for stages with no validator, and (per the literal-gating invariant) a no-op\n * whenever the checked slot isn't a fully-static literal.\n */\nexport function validateStageBody(stageName: string, body: Expr): void {\n  const validator = STAGE_BODY_VALIDATORS[stageName];\n  if (validator !== undefined) validator(body);\n}\n", "// `$out` collection-write translation: lowers\n//\n//   $$$.<coll>            = <RHS>;     // same-database write\n//   $$$[\"<coll>\"]         = <RHS>;     // same-database, bracket form\n//   $$$$.<db>.<coll>      = <RHS>;     // cross-database write\n//   $$$$[\"<db>\"][\"<coll>\"] = <RHS>;    // cross-database, bracket form\n//\n// into one or more pipeline stages ending with `$out`.\n//\n// The LHS shape (one or two static \u2014 dot or string-bracket \u2014 accesses on a\n// `DatabaseRef` or `ClusterRef`) is recognised by `detectOutAssign`. The RHS\n// must be rooted at `$$` (CollectionRef) \u2014 either bare (no extra stages) or\n// a chain of stage-producing method calls (`v1: .filter(<predicate>)` only;\n// the chain walker rejects other methods with an actionable hint).\n//\n// Statement-only, last-stage-only: `$out` writes downstream; nothing can\n// follow it in a pipeline. The caller (`generatePipeline` /\n// `lowerUpdateFilterWithLookups`) flips a `sawOut` flag after emission so\n// subsequent statements throw the trailing-stage error.\n//\n// Why a distinct LHS prefix and not `$ = \u2026`? jsmql reserves `$ = <expr>`\n// for *root-replacing* sugar (`$replaceWith`, `$facet`) \u2014 the bare `$` LHS\n// is the signal that the document itself is being replaced. `$out` does\n// not replace root; it writes the (filtered) stream elsewhere. The LHS\n// makes the write destination visible at a glance. See\n// `docs/specs/out-stage.md` and the convention note in\n// `docs/specs/replace-root-stage.md`.\n\nimport type { Expr, AssignExpr, Pipeline, PipelineStmt, UpdateFilter, UpdateOp } from \"./ast.ts\";\nimport { CodegenError, freshSubPipelineCtx, type GenerateCtx } from \"./codegen.ts\";\nimport { lowerLambdaPredicate, type SubPipelineLowerer, type SlotAllocator } from \"./lookup-translation.ts\";\nimport { lookupStreamMethod } from \"./stream-methods.ts\";\n\n// \u2500\u2500 Detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type OutTarget =\n  | { kind: \"same-db\"; coll: string; pos: number }\n  | { kind: \"cross-db\"; db: string; coll: string; pos: number };\n\n/**\n * One step of static (dot or string-literal-bracket) member access. Distinct\n * from `lookup-translation`'s helper because `$out` rejects computed brackets\n * outright (the destination must be statically known), while the lookup\n * helper silently returns null and lets the caller fall back.\n *\n * Returns `null` for non-access nodes (e.g. the leaf `DatabaseRef`).\n * Returns `{ ok: false, indexPos }` for a computed bracket \u2014 the caller\n * surfaces the precise \"literal collection name\" error using that pos.\n */\ntype AccessStep =\n  | { ok: true; name: string; object: Expr }\n  | { ok: false; indexPos: number; reason: \"computed\" | \"non-string-binding\" };\n\nfunction classifyStep(node: Expr, ctx?: GenerateCtx): AccessStep | null {\n  if (node.type === \"MemberAccess\") return { ok: true, name: node.member, object: node.object };\n  if (node.type === \"IndexAccess\") {\n    if (node.index.type === \"StringLiteral\") {\n      return { ok: true, name: node.index.value, object: node.object };\n    }\n    // `jsmql.compile` parameter binding \u2014 resolve at compile time when the\n    // value is a string. Anything else (number, array, missing binding) falls\n    // through to the standard \"must be literal / runtime expression\" error.\n    if (node.index.type === \"ParamRef\" && ctx?.bindings?.has(node.index.name)) {\n      const value = ctx.bindings.get(node.index.name);\n      if (typeof value === \"string\") {\n        return { ok: true, name: value, object: node.object };\n      }\n      return { ok: false, indexPos: node.index.pos, reason: \"non-string-binding\" };\n    }\n    return { ok: false, indexPos: node.index.pos, reason: \"computed\" };\n  }\n  return null;\n}\n\n/**\n * Recognise the `$out` LHS shape on an `AssignExpr.target`. Returns the\n * extracted target on a match, or `null` if the shape isn't even close to\n * `$out`-like \u2014 in which case the caller falls through to its other branches\n * (replace-root, lookup, regular update op, etc.).\n *\n * When the shape *is* `$out`-like but malformed (wrong segment count,\n * computed bracket), this throws a precise `CodegenError` \u2014 that's what we\n * want, because the user clearly meant to address a collection but the\n * shape doesn't quite parse as one.\n */\nexport function detectOutAssign(op: AssignExpr, ctx?: GenerateCtx): OutTarget | null {\n  const t = op.target;\n  // Cheap pre-filter: must be a member/index chain ending in `DatabaseRef` or\n  // `ClusterRef`. Anything else (FieldRef paths, bare CollectionRef, etc.) is\n  // not an `$out` target.\n  const leaf = findContextRefLeaf(t);\n  if (leaf === null) return null;\n\n  if (leaf.type === \"DatabaseRef\") {\n    // Expect exactly one access step: `$$$.<coll>` or `$$$[\"<coll>\"]`.\n    const step = classifyStep(t, ctx);\n    if (step === null) {\n      // Bare `$$$` on the LHS (no segment) \u2014 `$$$ = $$;` would never reach this\n      // branch (parser rejects assignment-to-non-path), but defend.\n      throw new CodegenError(\n        `'$$$' alone isn't a $out target \u2014 write '$$$.<coll>' (or '$$$[\"<coll>\"]') to write to a collection in the local database.`,\n        t.pos,\n      );\n    }\n    if (!step.ok) {\n      const why =\n        step.reason === \"non-string-binding\"\n          ? `the parameter binding must be a string (collection name is statically determined at compile time)`\n          : `not a runtime expression`;\n      throw new CodegenError(\n        `'$out' target must be a literal collection name \u2014 use '$$$.<coll>' or '$$$[\"<coll>\"]', ${why}. ` +\n          `If you need a parameterised target, use 'jsmql.compile' and pass the name in.`,\n        step.indexPos,\n      );\n    }\n    // step.ok \u2014 verify the inner is `DatabaseRef` and nothing deeper.\n    if (step.object.type !== \"DatabaseRef\") {\n      // Two-or-more segments after `$$$` \u2014 `$$$.a.b = \u2026`. Either too many segments\n      // for same-DB or the user meant the cross-DB four-dollar form.\n      throw new CodegenError(\n        `'$$$.<a>.<b>' has too many segments for a same-database $out target \u2014 use '$$$$.<db>.<coll>' (four \\$) for a cross-database write, ` +\n          `or '$$$.<coll>' (three \\$) for the local database.`,\n        t.pos,\n      );\n    }\n    return { kind: \"same-db\", coll: step.name, pos: t.pos };\n  }\n\n  // leaf is ClusterRef \u2014 expect exactly two access steps.\n  const outer = classifyStep(t, ctx);\n  if (outer === null) {\n    // Bare `$$$$` on LHS \u2014 unreachable through the parser, but defend.\n    throw new CodegenError(\n      `'$$$$' alone isn't a $out target \u2014 write '$$$$.<db>.<coll>' (or its bracket equivalents) to write to a collection in another database.`,\n      t.pos,\n    );\n  }\n  if (!outer.ok) {\n    const why =\n      outer.reason === \"non-string-binding\"\n        ? `the parameter binding must be a string (collection name is statically determined at compile time)`\n        : `not a runtime expression`;\n    throw new CodegenError(\n      `'$out' target must be a literal collection name \u2014 use '$$$$.<db>.<coll>' or bracketed equivalents, ${why}. ` +\n        `If you need a parameterised target, use 'jsmql.compile' and pass the name in.`,\n      outer.indexPos,\n    );\n  }\n  const inner = classifyStep(outer.object, ctx);\n  if (inner === null) {\n    // Only one segment after `$$$$` \u2014 `$$$$.<x> = \u2026`. Missing the collection.\n    throw new CodegenError(\n      `'$$$$.<x>' is missing the collection \u2014 write '$$$$.<db>.<coll>' (db, then collection), ` +\n        `or use '$$$.<coll>' (three \\$) for the local database.`,\n      t.pos,\n    );\n  }\n  if (!inner.ok) {\n    const why =\n      inner.reason === \"non-string-binding\"\n        ? `the parameter binding must be a string (database name is statically determined at compile time)`\n        : `not a runtime expression`;\n    throw new CodegenError(\n      `'$out' target must be a literal database name \u2014 use '$$$$.<db>.<coll>' or bracketed equivalents, ${why}. ` +\n        `If you need a parameterised target, use 'jsmql.compile' and pass the name in.`,\n      inner.indexPos,\n    );\n  }\n  if (inner.object.type !== \"ClusterRef\") {\n    // Three or more segments after `$$$$` \u2014 `$$$$.a.b.c = \u2026`. Too many.\n    throw new CodegenError(\n      `'$$$$.<a>.<b>.<c>' has too many segments for a $out target \u2014 '$out' writes to one collection in one database, so '$$$$.<db>.<coll>' is the deepest form.`,\n      t.pos,\n    );\n  }\n  return { kind: \"cross-db\", db: inner.name, coll: outer.name, pos: t.pos };\n}\n\n/**\n * Walk through member/index nesting to find the root context-ref leaf, if any.\n * Returns the leaf node so callers can branch on `DatabaseRef` vs `ClusterRef`,\n * or `null` if the chain doesn't bottom out in a context-ref (e.g. it's a\n * regular field path, a `CollectionRef`, etc.).\n */\nfunction findContextRefLeaf(node: Expr): { type: \"DatabaseRef\" | \"ClusterRef\" } | null {\n  let cur: Expr = node;\n  for (;;) {\n    if (cur.type === \"DatabaseRef\") return { type: \"DatabaseRef\" };\n    if (cur.type === \"ClusterRef\") return { type: \"ClusterRef\" };\n    if (cur.type === \"MemberAccess\" || cur.type === \"IndexAccess\") {\n      cur = cur.object;\n      continue;\n    }\n    return null;\n  }\n}\n\n// \u2500\u2500 RHS chain lowering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Walk the RHS chain rooted at `$$` (CollectionRef) and emit the prefix\n * pipeline stages, left-to-right. Returns the (possibly empty) stage list;\n * the caller appends the final `$out` stage.\n *\n * Supported RHS shapes:\n *   - bare `$$`                                    \u2192 []\n *   - `$$.filter(<predicate>)`                     \u2192 [{ $match: ... }]\n *   - chained stream-methods registry methods\n *     (`.slice`, `.map`, `.toSorted`, `.toReversed`,\n *     `.flatMap`, `.concat`) compose freely        \u2192 [<their stages>...]\n *\n * Unrecognised methods throw an actionable error naming the\n * stage-call alternative.\n */\nexport function lowerOutChain(\n  rhs: Expr,\n  outerCtx: GenerateCtx,\n  lowerBlock: SubPipelineLowerer,\n  allocSlot: SlotAllocator,\n): object[] {\n  // Bare `$$` \u2014 no extra stages.\n  if (rhs.type === \"CollectionRef\") return [];\n\n  // A method-call chain \u2014 walk it inside-out, then emit stages in source order.\n  if (rhs.type === \"MethodCall\") {\n    return walkChain(rhs, outerCtx, lowerBlock, allocSlot);\n  }\n\n  // Anything else \u2014 the RHS isn't rooted at `$$`. Diagnose.\n  throw new CodegenError(\n    `The right-hand side of '$$$.<coll> = \u2026' must start with '$$' (the current pipeline). ` +\n      `Write '$$$.<coll> = $$' to write the current stream as-is, or '$$$.<coll> = $$.filter(<predicate>)' to pre-filter before writing.`,\n    rhs.pos,\n  );\n}\n\n/**\n * Recursively walk a `$$.<method>(\u2026).<method>(\u2026)\u2026` chain. Emits stages in\n * source order. Each method-call layer must be one of the supported chain\n * methods (currently just `.filter`); unsupported methods throw with a\n * hint. The bottom of the chain must be a bare `$$` \u2014 anything else means\n * the chain isn't actually rooted at the current pipeline.\n */\nfunction walkChain(\n  call: Expr,\n  outerCtx: GenerateCtx,\n  lowerBlock: SubPipelineLowerer,\n  allocSlot: SlotAllocator,\n): object[] {\n  if (call.type !== \"MethodCall\") {\n    // Bottomed out somewhere other than `$$` \u2014 the chain isn't rooted at the\n    // current pipeline.\n    if (call.type === \"CollectionRef\") {\n      // Defensive \u2014 should be unreachable because the entry point handles the\n      // bare-CollectionRef case before calling walkChain.\n      return [];\n    }\n    throw new CodegenError(\n      `The right-hand side of '$$$.<coll> = \u2026' must be a chain rooted at '$$' (the current pipeline). ` +\n        `'$$$.<coll> = $$', '$$$.<coll> = $$.filter(<predicate>)' are the supported shapes today.`,\n      call.pos,\n    );\n  }\n\n  // First lower the receiver (the prefix of the chain), then append this\n  // method's stage(s) so source order is preserved.\n  const prefix: object[] =\n    call.object.type === \"CollectionRef\" ? [] : walkChain(call.object, outerCtx, lowerBlock, allocSlot);\n\n  const here = lowerChainMethod(call, outerCtx, lowerBlock, prefix, allocSlot);\n  if (here.replacesPreviousStage) prefix.pop();\n  prefix.push(...here.stages);\n  return prefix;\n}\n\n/**\n * Lower one method-call layer of a `$$.\u2026` chain into one or more pipeline\n * stages. `.filter(<predicate>)` \u2192 `$match` is special-cased so it can\n * compose with the existing query-translator (and emit `$expr` residuals);\n * every other method is routed through the shared `STREAM_METHODS` registry\n * (`.slice`, `.map`, `.toSorted`, `.toReversed`, `.flatMap`, `.concat`).\n *\n * Returns `{ stages, replacesPreviousStage? }` \u2014 `.toReversed()` reads\n * `prevStages` and may flip the preceding `$sort`, in which case it asks\n * the caller to drop the last emitted stage before appending its own.\n */\nfunction lowerChainMethod(\n  call: Expr & { type: \"MethodCall\" },\n  outerCtx: GenerateCtx,\n  lowerBlock: SubPipelineLowerer,\n  prevStages: readonly object[],\n  allocSlot: SlotAllocator,\n): { stages: object[]; replacesPreviousStage?: boolean } {\n  if (call.method === \"filter\") {\n    return { stages: lowerFilterAsMatch(call, outerCtx, lowerBlock) };\n  }\n  const def = lookupStreamMethod(call.method);\n  if (def !== null) {\n    def.validate(call.args, call.pos);\n    // `inSubPipeline = false` \u2014 `$out` chains live at the outer pipeline level,\n    // not inside a `$unionWith.pipeline` body.\n    const result = def.lower(call.args, outerCtx, call.pos, lowerBlock, prevStages, allocSlot, false);\n    return { stages: result.stages, replacesPreviousStage: result.replacesPreviousStage };\n  }\n  // Method not in the stream-methods registry either. Mention the stage-call\n  // alternative so the user has an immediate workaround.\n  const equivalent = STAGE_EQUIVALENT_HINT[call.method];\n  const hint =\n    equivalent !== undefined\n      ? ` Use '${equivalent}' as a separate stage before the '$out' instead.`\n      : ` Add the equivalent stage call (e.g. '$sort({ \u2026 })', '$skip(N)', '$limit(N)') before the '$out' instead.`;\n  throw new CodegenError(`'$$.${call.method}(...)' isn't a recognised chain method for a '$out' RHS.${hint}`, call.pos);\n}\n\nconst STAGE_EQUIVALENT_HINT: Record<string, string> = {\n  map: \"$project({...}) or $addFields({...})\",\n  sort: \"$sort({ field: 1 | -1 })\",\n  slice: \"$skip(N); $limit(M)\",\n  reduce: \"$group({ ... })\",\n  flatMap: \"$unwind\",\n  flat: \"$unwind\",\n};\n\n/**\n * `$$.filter(<lambda>)` \u2192 `[{ $match: <translated> }]`. After validating the\n * arrow shape (exactly one single-parameter predicate), the body is lowered via\n * the shared `lowerLambdaPredicate` from lookup-translation, which both\n * lookup/union/facet use:\n *   - Expression body \u2192 match-translation's engine: translatable conjuncts emit\n *     index-friendly `{ field: value }` syntax, residuals ride in `$expr`.\n *   - Block body \u2192 the caller-supplied `lowerBlock` (each statement \u2192 a stage).\n * `$.<field>` references on the param are rejected \u2014 the parameter *is* the\n * current document, so they'd be ambiguous (mirrors the facet-form rule).\n */\nfunction lowerFilterAsMatch(\n  call: Expr & { type: \"MethodCall\" },\n  outerCtx: GenerateCtx,\n  lowerBlock: SubPipelineLowerer,\n): object[] {\n  if (call.args.length !== 1) {\n    throw new CodegenError(\n      `'$$.filter(<predicate>)' expects exactly one arrow predicate, got ${call.args.length}.`,\n      call.pos,\n    );\n  }\n  const arg = call.args[0];\n  if (arg.type !== \"Lambda\") {\n    throw new CodegenError(\n      `'$$.filter(<predicate>)' requires an arrow predicate, e.g. \\`$$$.coll = $$.filter(d => d.active)\\`.`,\n      \"pos\" in arg ? arg.pos : call.pos,\n    );\n  }\n  if (arg.params.length !== 1) {\n    throw new CodegenError(\n      `'$$.filter(<predicate>)' takes a single-parameter arrow (the current document), got ${arg.params.length}.`,\n      arg.pos,\n    );\n  }\n  // Shared expr-or-block predicate lowering (see `lowerLambdaPredicate`). A\n  // `$out` chain has no `let` slot, so a predicate that references the local doc\n  // (`$.<field>`, captured as a non-empty `letVars`) is rejected in favour of the\n  // lambda parameter.\n  return lowerLambdaPredicate(arg, outerCtx, lowerBlock, {\n    freshCtx: freshSubPipelineCtx,\n    onLocalRef: (_letVars, param, pos) => {\n      throw new CodegenError(\n        `\\`$.<field>\\` inside '$$.filter(<predicate>)' in a '$out' chain is not supported \u2014 the lambda's parameter \\`${param}\\` IS the current document. ` +\n          `Write \\`${param}.<field>\\` instead.`,\n        pos,\n      );\n    },\n    missingBody: () => {\n      throw new CodegenError(\n        `'$$.filter(<predicate>)' lambda is missing a body \u2014 internal parser bug; please report.`,\n        arg.pos,\n      );\n    },\n  });\n}\n\n// \u2500\u2500 Public entry point: lower an `$out` assignment to stages \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Compose RHS-prefix stages with the trailing `{ $out: <target> }`. Returns\n * the stage list to splice into the surrounding pipeline. The caller is\n * responsible for flushing any preceding update-op buffer and setting the\n * \"saw $out\" flag so subsequent statements throw the trailing-stage error.\n */\nexport function lowerOut(\n  op: AssignExpr,\n  target: OutTarget,\n  outerCtx: GenerateCtx,\n  lowerBlock: SubPipelineLowerer,\n  allocSlot: SlotAllocator,\n): object[] {\n  const prefix = lowerOutChain(op.value, outerCtx, lowerBlock, allocSlot);\n  const body: string | { db: string; coll: string } =\n    target.kind === \"same-db\" ? target.coll : { db: target.db, coll: target.coll };\n  prefix.push({ $out: body });\n  return prefix;\n}\n\n// \u2500\u2500 Mode-gate helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Cheap walk: does `node` contain an `$out` assignment? Used by Filter /\n * `jsmql.expr` mode gates to surface a precise \"use Pipeline mode\" error.\n * Recognising only the canonical AssignExpr-target shape (one or two\n * static accesses on `DatabaseRef`/`ClusterRef`) is enough \u2014 anything else\n * never participates in `$out` lowering anyway.\n */\nexport function containsOutAssign(node: Expr | Pipeline | UpdateFilter): boolean {\n  return walkContainsOut(node);\n}\n\nfunction walkContainsOut(node: Expr | Pipeline | UpdateFilter | PipelineStmt | UpdateOp): boolean {\n  if (node.type === \"Pipeline\") return node.stmts.some(walkContainsOut);\n  if (node.type === \"UpdateFilter\") return node.ops.some(walkContainsOut);\n  if (node.type === \"AssignExpr\") {\n    // Looks-like-$out shape on the target?\n    if (findContextRefLeaf(node.target) !== null) {\n      // Confirm it really *is* an $out shape (vs a malformed one we'd reject).\n      // We can't call `detectOutAssign` here because that throws on malformed\n      // shapes; the mode-gate just wants to know if the user's syntax is\n      // reaching for `$out` at all, malformed or not.\n      return true;\n    }\n    return false;\n  }\n  if (node.type === \"DeleteStmt\") return false;\n  if (node.type === \"LetDecl\") return false;\n  if (node.type === \"ArrayLiteral\") {\n    for (const el of node.elements) {\n      if (el.type === \"SpreadElement\") continue;\n      if (walkContainsOut(el)) return true;\n    }\n    return false;\n  }\n  return false;\n}\n", "// System / diagnostic stage translation: lowers scope-encoding method-call\n// sugar into MongoDB's diagnostic source stages.\n//\n//   $$.indexStats()                          \u2192 { $indexStats: {} }\n//   $$.collStats({ storageStats: {} })       \u2192 { $collStats: { storageStats: {} } }\n//   $$$$.currentOp({ allUsers: true })       \u2192 { $currentOp: { allUsers: true } }\n//   $$$$.shardedDataDistribution()           \u2192 { $shardedDataDistribution: {} }\n//\n// These stages don't transform an incoming stream \u2014 they *produce* one (index\n// metadata, collection stats, running ops, \u2026) \u2014 so each must be the pipeline's\n// first stage. They also differ by *where* they legally run, and the\n// context-ref prefix encodes exactly that scope. Two tiers are in use:\n//\n//   $$    current collection   \u2192 db.coll.aggregate()  ($indexStats, $collStats, \u2026)\n//   $$$$  cluster / server      \u2192 admin (or config) DB ($currentOp, $listSessions,\n//                                                        $shardedDataDistribution, \u2026)\n//\n// $$$ (current database) carries NO diagnostics: $currentOp & friends run on the\n// admin database, never the current one, so they're cluster-scoped, not\n// database-scoped. Because the prefix *is* the scope, a stage used at the wrong\n// scope is a compile-time error (`$$.currentOp()` \u2192 \"write '$$$$.currentOp(...)'\").\n//\n// Disambiguation vs `$lookup` (`$$$.<coll>.find(...)`): a diagnostic call is a\n// *direct* MethodCall on a bare ref node (`object` is `DatabaseRef`), whereas a\n// lookup's `object` is a `MemberAccess` wrapping the ref. The two shapes never\n// collide. On `$$`, the diagnostic method names never clash with the reserved\n// `.push` (union) / `.filter` (facet) methods, which are excluded here.\n//\n// The scope \u2194 stage mapping lives entirely in the `diagnostic` field of the\n// STAGES registry (src/stages.ts) \u2014 the single source of truth. This module\n// only derives the callable method name (`stageName` minus the leading `$`)\n// and the per-scope suggestion lists from it.\n//\n// See docs/specs/system-stages.md for the full design and error catalog.\n\nimport type { Expr } from \"./ast.ts\";\nimport { CodegenError } from \"./codegen.ts\";\nimport { closestNameTo, didYouMean } from \"./levenshtein.ts\";\nimport { STAGES } from \"./stages.ts\";\n\ntype Scope = \"collection\" | \"database\" | \"cluster\";\n\n// Context-ref node type \u2194 scope, and scope \u2194 display prefix.\nconst REF_SCOPE: Record<string, Scope> = {\n  CollectionRef: \"collection\",\n  DatabaseRef: \"database\",\n  ClusterRef: \"cluster\",\n};\nconst SCOPE_PREFIX: Record<Scope, string> = { collection: \"$$\", database: \"$$$\", cluster: \"$$$$\" };\nconst SCOPE_DRIVER: Record<Scope, string> = {\n  collection: \"db.coll.aggregate()\",\n  database: \"db.aggregate()\",\n  cluster: \"the admin database\",\n};\n\n// `$$` methods owned by other sugars \u2014 never treated as diagnostics.\nconst RESERVED_COLLECTION_METHODS = new Set([\"push\", \"filter\"]);\n\ntype DiagnosticDef = { stageName: string; scope: Scope; options: boolean };\n\n// Derived from STAGES once at module load: method name \u2192 diagnostic def, and\n// scope \u2192 method names (for \"did you mean\" suggestions).\nconst DIAGNOSTICS_BY_METHOD: Map<string, DiagnosticDef> = new Map();\nconst METHODS_BY_SCOPE: Map<Scope, string[]> = new Map([\n  [\"collection\", []],\n  [\"database\", []],\n  [\"cluster\", []],\n]);\nfor (const [stageName, def] of Object.entries(STAGES)) {\n  if (def.diagnostic === undefined) continue;\n  const method = stageName.slice(1); // drop leading \"$\"\n  const entry: DiagnosticDef = { stageName, scope: def.diagnostic.scope, options: def.diagnostic.options };\n  DIAGNOSTICS_BY_METHOD.set(method, entry);\n  METHODS_BY_SCOPE.get(def.diagnostic.scope)!.push(method);\n}\n\nexport type SystemStageCall = {\n  stageName: string;\n  scope: Scope;\n  /** The options-object argument, or null when called with no arguments. */\n  optionsExpr: Expr | null;\n  /** Position of the `.<method>(...)` call site (for first-stage / arg errors). */\n  callPos: number;\n};\n\n/**\n * Cheap shape check: is `expr` a *direct* method call on a bare context-ref\n * node that should be handled as a diagnostic source stage? Used by the\n * `index.ts` dispatch auto-wrap to route such a top-level call into Pipeline\n * mode, and by `pipeline.ts` to gate `resolveSystemStageCall`.\n *\n * `$$` shares its method namespace with the union (`.push`) and facet\n * (`.filter`) sugars, so on `CollectionRef` this only claims a method that is\n * an actual diagnostic \u2014 at any scope, so `$$.currentOp()` still routes here to\n * get the wrong-scope hint \u2014 or a near-typo of one (`$$.indexStat()` \u2192 \"did you\n * mean indexStats\"). Anything else (`$$.pop()`) returns `false` and falls\n * through to the union validator's own `.push` / `.filter` guidance.\n *\n * On `$$$` / `$$$$` a direct call is a diagnostic-only namespace (lookups use a\n * `.coll.find(...)` chain, whose receiver is a `MemberAccess`, not a bare ref),\n * so every direct call routes here \u2014 wrong-scope and misspelled methods\n * included \u2014 to get a precise error downstream.\n */\nexport function isSystemStageCall(expr: Expr): boolean {\n  if (expr.type !== \"MethodCall\") return false;\n  const scope = REF_SCOPE[expr.object.type];\n  if (scope === undefined) return false;\n  if (scope !== \"collection\") return true;\n  if (RESERVED_COLLECTION_METHODS.has(expr.method)) return false;\n  if (DIAGNOSTICS_BY_METHOD.has(expr.method)) return true;\n  return closestNameTo(expr.method, DIAGNOSTICS_BY_METHOD.keys()) !== null;\n}\n\n/**\n * Resolve a direct ref method call (one that `isSystemStageCall` accepts) into\n * a validated `SystemStageCall`, or throw an actionable `CodegenError`:\n *\n *   - wrong scope (`$$.currentOp()` \u2014 a database stage) \u2192 points at the right prefix\n *   - unknown method (`$$.indexStat()`) \u2192 `Did you mean 'indexStats'?`\n *   - a no-option stage given an argument (`$$.indexStats({})`)\n *   - an option-bearing stage given >1 arg or a non-object arg\n *\n * Caller must have already checked `isSystemStageCall(expr)`.\n */\nexport function resolveSystemStageCall(expr: Expr): SystemStageCall {\n  if (expr.type !== \"MethodCall\") {\n    throw new CodegenError(\"jsmql internal error (please report): resolveSystemStageCall on a non-MethodCall.\", 0);\n  }\n  const scope = REF_SCOPE[expr.object.type];\n  const prefix = SCOPE_PREFIX[scope];\n  const method = expr.method;\n  const refPos = expr.object.pos;\n\n  const def = DIAGNOSTICS_BY_METHOD.get(method);\n  if (def === undefined) {\n    // Suggest across *all* scopes (with the right prefix) so a typo of a\n    // wrong-scope stage still lands \u2014 and so a scope with no diagnostics of its\n    // own (e.g. `$$$`) still gives an actionable pointer.\n    const hint = didYouMean(\n      method,\n      DIAGNOSTICS_BY_METHOD.keys(),\n      (s) => `${SCOPE_PREFIX[DIAGNOSTICS_BY_METHOD.get(s)!.scope]}.${s}(...)`,\n    );\n    const here = METHODS_BY_SCOPE.get(scope)!;\n    const base =\n      here.length > 0\n        ? `'${prefix}' (${scope} reference) supports the ${scope}-scoped system stages: ${formatList(here)}.`\n        : `'${prefix}' (${scope} reference) has no diagnostic source stages \u2014 collection diagnostics use '$$', server/cluster diagnostics use '$$$$'.`;\n    throw new CodegenError(`'${prefix}.${method}(...)' is not a known diagnostic stage. ${base}${hint}`, refPos);\n  }\n  if (def.scope !== scope) {\n    throw new CodegenError(\n      `'${method}' is a ${def.scope}-scoped system stage \u2014 write '${SCOPE_PREFIX[def.scope]}.${method}(...)' ` +\n        `(the '${SCOPE_PREFIX[def.scope]}' ${def.scope} reference, run on ${SCOPE_DRIVER[def.scope]}), not '${prefix}'.`,\n      refPos,\n    );\n  }\n\n  // Argument shape.\n  if (expr.args.length > 1) {\n    throw new CodegenError(\n      `'${prefix}.${method}(...)' takes ${def.options ? \"at most one options object\" : \"no options\"}, ` +\n        `but got ${expr.args.length} arguments.`,\n      expr.pos,\n    );\n  }\n  if (expr.args.length === 0) {\n    return { stageName: def.stageName, scope, optionsExpr: null, callPos: expr.pos };\n  }\n  const arg = expr.args[0];\n  if (arg.type === \"SpreadElement\") {\n    throw new CodegenError(`'${prefix}.${method}(...)' does not accept a spread argument.`, arg.argument.pos);\n  }\n  if (!def.options) {\n    throw new CodegenError(`'${prefix}.${method}()' takes no options \u2014 call it with no arguments.`, arg.pos);\n  }\n  if (arg.type !== \"ObjectLiteral\") {\n    throw new CodegenError(\n      `'${prefix}.${method}(...)' expects an options object literal (e.g. \\`${prefix}.${method}({ ... })\\`), ` +\n        `not a ${describeArg(arg)}.`,\n      arg.pos,\n    );\n  }\n  return { stageName: def.stageName, scope, optionsExpr: arg, callPos: expr.pos };\n}\n\n/** Message for a diagnostic source stage used anywhere but the first stage. */\nexport function notFirstStageMessage(call: SystemStageCall): string {\n  const prefix = SCOPE_PREFIX[call.scope];\n  const method = call.stageName.slice(1);\n  return (\n    `'${prefix}.${method}(...)' produces the pipeline's source documents (\\`${call.stageName}\\`), ` +\n    `so it must be the first stage. Move it to the front of the pipeline.`\n  );\n}\n\nfunction describeArg(arg: Expr): string {\n  if (arg.type === \"NumberLiteral\" || arg.type === \"StringLiteral\" || arg.type === \"BooleanLiteral\") {\n    return `${arg.type.replace(/Literal$/, \"\").toLowerCase()} literal`;\n  }\n  if (arg.type === \"NullLiteral\") return \"`null`\";\n  if (arg.type === \"ArrayLiteral\") return \"array\";\n  return \"non-object expression\";\n}\n\nfunction formatList(methods: string[]): string {\n  return methods.map((m) => `.${m}()`).join(\", \");\n}\n", "// Pipeline detection and lowering.\n//\n// Owns everything stage-related so codegen.ts stays focused on a single\n// expression. Public surface:\n//   - isPipelineAst(ast)   \u2014 true if the AST root looks like an aggregation pipeline\n//   - generatePipeline(ast) \u2014 compile a pipeline-shaped AST to an MQL stage array\n//\n// Detection rule: the AST root is an ArrayLiteral whose *first* element is a\n// recognised stage shape (single-key object literal `{ $stage: body }` whose\n// key is in STAGES, or `$stage(body)` whose name is in STAGES). Once\n// triggered, every remaining element must also be a stage shape \u2014 otherwise\n// CodegenError pinpoints the offending element. If the first element does\n// not look like a stage, the array is left to the existing expression-mode\n// codegen (so `jsmql(\"[1, 2, 3]\")` still compiles as a literal array).\n//\n// $match has a special-case body lowering with two layers:\n//   1. An object-literal body is treated as a raw MongoDB query document and\n//      passed through verbatim. This is the explicit escape hatch for users\n//      who want strict aggregation `$eq` semantics (`$match({ $expr: ... })`).\n//   2. An expression body goes through `translateMatchBody` (see\n//      `match-translation.ts`), which emits an index-friendly query document\n//      for the translatable subset (field-vs-literal comparisons combined\n//      with `&&`/`||`). Untranslatable sub-expressions are returned as a\n//      residual and wrapped in `$expr`, yielding e.g.\n//      `{ $match: { status: \"active\", $expr: <residual> } }` \u2014 indexes still\n//      apply to the `status` predicate.\n// See `docs/specs/match-query-translation.md` for the translation rules and\n// the four documented semantic divergences between query-language equality\n// and aggregation `$eq`.\n//\n// `let` bindings (see docs/specs/let-bindings.md) are pipeline-scoped local\n// variables that materialise under a single compiler-owned namespace field\n// (`__jsmql.<name>`) for the duration of the pipeline, with one trailing\n// `$unset: \"__jsmql\"` stage to clean up. The let scope is threaded through\n// stage lowering via a GenerateCtx so subsequent stages can resolve bare-\n// identifier references to the corresponding field path. Reshape-clearing\n// stages (`$group`, `$bucket`, `$bucketAuto`, `$replaceRoot`, `$replaceWith`)\n// drop the document and so drop all lets; later references become precise\n// \"let X can't be read after $group\" errors. Sub-pipelines (`$lookup.pipeline`,\n// `$unionWith.pipeline`, `$facet.*`) get a fresh empty let scope \u2014 outer lets\n// do not cross sub-pipeline boundaries in v1. The `$match` translator returns\n// AST residuals that the caller re-lowers; we re-lower them with the current\n// pipeline ctx so a let referenced inside an otherwise-translatable $match body\n// still resolves correctly.\n\nimport type {\n  Expr,\n  ArrayElement,\n  UpdateOp,\n  AssignExpr,\n  Pipeline,\n  LetDecl,\n  PipelineStmt,\n  UpdateFilter,\n  CallArg,\n} from \"./ast.ts\";\nimport {\n  generateWithCtx,\n  generateUpdateOpGroups,\n  generateUpdateFilter,\n  updateOpWritePath,\n  tryRewriteMutatorCall,\n  CodegenError,\n  EMPTY_CTX,\n  extendCtxLets,\n  clearCtxLets,\n  ctxHasLets,\n  freshSubPipelineCtx,\n  internalError,\n  type GenerateCtx,\n} from \"./codegen.ts\";\nimport { didYouMean } from \"./levenshtein.ts\";\nimport { lookupStage, STAGES, stageMustBeFirst, stageMustBeLast, stageForbiddenIn } from \"./stages.ts\";\nimport { translateMatchBody, mergeTranslatedQuery } from \"./match-translation.ts\";\nimport {\n  buildPipelineFormPredicate,\n  detectLookupCall,\n  lowerLookup,\n  extractLookupCalls,\n  createSlotAllocator,\n  predicateReferencesOuterDoc,\n  validateLookupShape,\n  translatePredicate,\n  extractLookupTarget,\n  lowerLambdaPredicate,\n  type LookupCall,\n  type SlotAllocator,\n  type SubPipelineLowerer,\n} from \"./lookup-translation.ts\";\nimport { detectUnionPush, lowerUnionPush } from \"./union-translation.ts\";\nimport { detectFacetShape, lowerFacet } from \"./facet-translation.ts\";\nimport { validateStageBody, validateMatchPlacement } from \"./stage-validation.ts\";\nimport { detectOutAssign, lowerOut } from \"./out-translation.ts\";\nimport {\n  isSystemStageCall,\n  notFirstStageMessage,\n  resolveSystemStageCall,\n  type SystemStageCall,\n} from \"./system-stage-translation.ts\";\nimport {\n  collectStreamChain,\n  detectArrayReducerWrap,\n  detectDictBuildWrap,\n  detectReduceWrap,\n  lookupStreamMethod,\n  lowerDictBuildWrap,\n  lowerReduceWrap,\n  streamMethodNames,\n  type ArrayReducerWrap,\n  type MethodCallNode,\n} from \"./stream-methods.ts\";\n\ntype StageShape = { name: string; body: Expr };\n\n/** Stages that replace the document and so drop all in-scope `let` bindings. */\nconst RESHAPE_CLEARING_STAGES = new Set([\"$group\", \"$bucket\", \"$bucketAuto\", \"$replaceRoot\", \"$replaceWith\", \"$facet\"]);\n\n/** Compiler-owned namespace for materialised `let` bindings. */\nconst LET_NAMESPACE = \"__jsmql\";\n\n/**\n * Peephole: skip the trailing `{ $unset: \"__jsmql\" }` cleanup when the\n * previous stage already dropped the document (Wave 5 #36). After\n * `$replaceWith` / `$replaceRoot` / `$group` / `$bucket*` / `$facet`, the\n * `__jsmql` field no longer exists on the output doc \u2014 cleaning up an\n * absent path is just noise. One stage saved per pipeline in the common\n * case.\n *\n * Detection mirrors RESHAPE_CLEARING_STAGES: any stage that the\n * scope-clearing machinery already treats as a reshape boundary also\n * eats the namespace field, so the cleanup is unconditionally redundant\n * after it.\n */\nfunction shouldSkipTrailingNamespaceUnset(stages: readonly unknown[]): boolean {\n  if (stages.length === 0) return false;\n  const last = stages[stages.length - 1];\n  if (last === null || typeof last !== \"object\") return false;\n  const keys = Object.keys(last as Record<string, unknown>);\n  if (keys.length !== 1) return false;\n  return RESHAPE_CLEARING_STAGES.has(keys[0]);\n}\n\n/**\n * Loose detection: does `el` look like the user *intended* a pipeline stage?\n * Used only for top-level detection so a typo like `{ $macth: ... }` triggers\n * pipeline mode and surfaces a precise error instead of silently compiling\n * the array as a value expression. Returns true for:\n *   - any single- or multi-entry ObjectLiteral whose first static key starts\n *     with `$` (covers correctly-spelled stages, typos, and accidental\n *     multi-key stage objects)\n *   - any OperatorCall whose name is a registered stage\n * False for plain values, computed keys, spreads, expression operator calls,\n * etc. \u2014 these stay in expression mode.\n */\nfunction isStageCandidate(el: ArrayElement): boolean {\n  if (el.type === \"SpreadElement\") return false;\n  // Update ops (`$.a = 1`, `delete $.x`) and `let` bindings are pipeline\n  // statements \u2014 they lower to $set / $unset stages. Recognising them here\n  // flips the array into pipeline mode even when no `$stage`-shaped element\n  // comes first (`[let x = 5, $match(x > 0)]` is a pipeline).\n  if (el.type === \"AssignExpr\" || el.type === \"DeleteStmt\" || el.type === \"LetDecl\") {\n    return true;\n  }\n  if (el.type === \"ObjectLiteral\") {\n    if (el.entries.length === 0) return false;\n    const first = el.entries[0];\n    if (first.type !== \"KeyValueEntry\") return false;\n    if (first.key.kind !== \"static\") return false;\n    return first.key.name.startsWith(\"$\");\n  }\n  // Any `$<name>(...)` call at the array root is treated as a stage candidate\n  // \u2014 even when `<name>` isn't a known stage. This makes typos like\n  // `$prject({...})` surface a \"not a known stage\" error instead of silently\n  // compiling as a value array of expression-operator results. Top-level\n  // value arrays of operator calls are vanishingly rare in real aggregation\n  // use; copy-pasted MongoDB pipelines are the common case.\n  if (el.type === \"OperatorCall\") return true;\n  // `$$.push(...)` is a stage-shaped statement \u2014 it lowers to `$unionWith`\n  // stages. Recognising it here flips the array into pipeline mode so a\n  // bracketed `[$$.push(...), $sort(...)]` works and a sub-pipeline carrying\n  // a push (e.g. `$facet.*`) routes through the sub-pipeline path that\n  // pre-rejects it with a precise hoist-to-outer hint.\n  if (el.type === \"MethodCall\" && detectUnionPush(el as Expr) !== null) return true;\n  // `$$.indexStats()` / `$$$$.currentOp()` / `$$$$.shardedDataDistribution()` \u2014\n  // a diagnostic source stage. Direct method call on a bare context-ref node;\n  // it lowers to a `$<stage>` source. Recognising it here flips a bracketed\n  // `[$$.indexStats(), $sort(...)]` into pipeline mode (same pattern as the\n  // `detectUnionPush` line above).\n  if (el.type === \"MethodCall\" && isSystemStageCall(el as Expr)) return true;\n  return false;\n}\n\n/**\n * Strict shape validation for elements once pipeline mode is active. Returns\n * null when the element does not validate as a real stage; callers turn that\n * into a precise CodegenError via formatNotAStageError.\n */\nfunction asStageShape(el: ArrayElement): StageShape | null {\n  if (el.type === \"SpreadElement\") return null;\n\n  // Stage-object form: `{ $stage: <body> }` \u2014 single static $-key.\n  if (el.type === \"ObjectLiteral\") {\n    if (el.entries.length !== 1) return null;\n    const entry = el.entries[0];\n    if (entry.type !== \"KeyValueEntry\") return null;\n    if (entry.key.kind !== \"static\") return null;\n    if (!lookupStage(entry.key.name)) return null;\n    return { name: entry.key.name, body: entry.value };\n  }\n\n  // Stage-call form: `$stage(<body>)` or `$stage({ ... })` \u2014 exactly one arg.\n  if (el.type === \"OperatorCall\") {\n    if (!lookupStage(el.name)) return null;\n    if (el.args.length !== 1) return null;\n    const arg = el.args[0];\n    if (arg.type === \"SpreadElement\") return null;\n    return { name: el.name, body: arg };\n  }\n\n  return null;\n}\n\nexport function isPipelineAst(ast: Expr): boolean {\n  if (ast.type !== \"ArrayLiteral\") return false;\n  if (ast.elements.length === 0) return false;\n  return isStageCandidate(ast.elements[0]);\n}\n\n// \u2500\u2500 Structural stage-placement validation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// MongoDB rejects a pipeline at build time when a stage sits in an illegal\n// position: a source stage ($geoNear, $collStats, $changeStream, \u2026) anywhere\n// but first; a write stage ($out, $merge) anywhere but last; a stage forbidden\n// inside a $facet / $lookup / $unionWith sub-pipeline. We catch all of these at\n// compile time. The rules live declaratively in the STAGES registry (`position`\n// / `forbiddenIn`, read via stageMustBeFirst / stageMustBeLast / stageForbiddenIn);\n// this validator only applies them. See docs/specs/pipeline-validation.md.\n//\n// The sugar forms ($out via `$$$.<coll> = \u2026`, system stages via\n// `$$.indexStats()`) keep their own dedicated, sugar-aware messages and feed\n// this validator through `markSugarOut` for the must-be-last \"after\" error.\n\ntype ContainerKind = \"top\" | \"facet\" | \"lookup\" | \"unionWith\";\n\ntype TerminalState = { stageName: string; pos: number; viaSugar: boolean };\n\ntype PipelineValidator = {\n  /** Call at the top of every element/statement iteration, before lowering it. */\n  checkBeforeElement: (pos: number) => void;\n  /**\n   * Call for a literal stage (resolved by asStageShape) BEFORE pushing it.\n   * `userIndex` is the loop index \u2014 the user-authored position in THIS pipeline.\n   * Order: forbidden-in-context \u2192 must-be-first \u2192 record must-be-last \u2192\n   * (for `$match`) query-operator placement ($text-first, $near/$where bans).\n   */\n  checkStage: (name: string, pos: number, userIndex: number, body: Expr) => void;\n  /** The sugar `$out` paths call this so the unified \"after terminal\" check fires. */\n  markSugarOut: (pos: number) => void;\n};\n\nfunction makePipelineValidator(container: ContainerKind): PipelineValidator {\n  let terminal: TerminalState | null = null;\n  return {\n    checkBeforeElement(pos: number): void {\n      if (terminal !== null) throw makeAfterTerminalError(terminal, pos);\n    },\n    checkStage(name: string, pos: number, userIndex: number, body: Expr): void {\n      const def = lookupStage(name);\n      if (def === undefined) return; // asStageShape already guaranteed it; defensive\n      if (container !== \"top\" && stageForbiddenIn(def, container)) {\n        throw new CodegenError(forbiddenInContextMessage(name, container), pos);\n      }\n      // Key on the user-authored index, NOT out.length: prologue $lookup/$set\n      // stages (from prior `let`/lookup statements or this stage's own buried\n      // lookups) inflate out.length, but every prior user element emits \u22651\n      // stage, so `userIndex > 0` \u27FA a real preceding stage exists.\n      if (stageMustBeFirst(def) && userIndex > 0) {\n        throw new CodegenError(mustBeFirstLiteralMessage(name), pos);\n      }\n      if (stageMustBeLast(def)) terminal = { stageName: name, pos, viaSugar: false };\n      if (name === \"$match\") {\n        validateMatchPlacement(body, { isTopLevel: container === \"top\", isFirstStage: userIndex === 0 });\n      }\n    },\n    markSugarOut(pos: number): void {\n      terminal = { stageName: \"$out\", pos, viaSugar: true };\n    },\n  };\n}\n\n/**\n * Error raised when any stage appears after a must-be-last (terminal) stage.\n * The sugar `$out` form keeps its original `'$$$.<coll> = \u2026'` wording; literal\n * terminal stages ($out / $merge / $changeStreamSplitLargeEvent) name the stage.\n */\nfunction makeAfterTerminalError(terminal: TerminalState, afterPos: number): CodegenError {\n  if (terminal.viaSugar) {\n    return new CodegenError(\n      `'$out' must be the last stage in a pipeline. Move this statement before the '$$$.<coll> = \u2026' write (at position ${terminal.pos}), ` +\n        `or remove it.`,\n      afterPos,\n    );\n  }\n  return new CodegenError(\n    `'${terminal.stageName}' must be the last stage in a pipeline \u2014 nothing can run after it. ` +\n      `Move it to the end of the pipeline, or remove the stage(s) that follow it.`,\n    afterPos,\n  );\n}\n\n/** Message for a source stage (must-be-first) used in a non-first position, literal form. */\nfunction mustBeFirstLiteralMessage(stageName: string): string {\n  return (\n    `'${stageName}' must be the first stage in a pipeline \u2014 it produces the pipeline's source documents, ` +\n    `so nothing can run before it. Move it to the front, or remove the stage(s) that precede it.`\n  );\n}\n\n/** Message for a stage used inside a sub-pipeline container that forbids it. */\nfunction forbiddenInContextMessage(stageName: string, container: \"facet\" | \"lookup\" | \"unionWith\"): string {\n  const owner = container === \"facet\" ? \"$facet\" : container === \"lookup\" ? \"$lookup\" : \"$unionWith\";\n  return (\n    `'${stageName}' is not allowed inside a '${owner}' sub-pipeline. ` + `Move it to the outer (top-level) pipeline.`\n  );\n}\n\n/** Maps a sub-pipeline-owning stage to its container kind. */\nfunction containerKindFor(stageName: string): \"facet\" | \"lookup\" | \"unionWith\" {\n  if (stageName === \"$facet\") return \"facet\";\n  if (stageName === \"$unionWith\") return \"unionWith\";\n  return \"lookup\";\n}\n\n/**\n * Compile a pipeline-shaped ArrayLiteral AST to an MQL pipeline (stage array).\n *\n * Caller must have verified `isPipelineAst(ast)` first; we still validate\n * every element here and throw a precise CodegenError on the first non-stage\n * element so the error message points at the offending position.\n *\n * Consecutive update op elements (`$.a = 1`, `delete $.x`) coalesce through\n * the same algorithm `jsmql()` uses at the top level \u2014 see\n * `generateUpdateOpGroups` in codegen.ts. Non-update op stages flush the\n * current update op buffer and emit its compiled $set/$unset stage(s) inline.\n *\n * `let` bindings extend a pipeline-scoped GenerateCtx that downstream stages\n * inherit; reshape-clearing stages drop the scope; a trailing `$unset` is\n * appended once if any let was declared.\n */\nexport function generatePipeline(ast: Expr, startCtx: GenerateCtx = EMPTY_CTX): unknown[] {\n  if (ast.type !== \"ArrayLiteral\") {\n    internalError(\"generatePipeline expects an ArrayLiteral AST\");\n  }\n  const out: unknown[] = [];\n  let updateBuffer: UpdateOp[] = [];\n  let ctx: GenerateCtx = startCtx;\n  let everHadLet = false;\n  const validator = makePipelineValidator(\"top\");\n  const tracking = makeSlotTracking();\n\n  const flushUpdateOps = () => {\n    if (updateBuffer.length === 0) return;\n    for (const stage of generateUpdateOpGroups(updateBuffer, ctx)) out.push(stage);\n    updateBuffer = [];\n  };\n\n  ast.elements.forEach((rawEl, i) => {\n    validator.checkBeforeElement(rawEl.pos);\n    let el: ArrayElement = rawEl;\n    // Statement-position mutator rewrite: a `$.<field>.sort(...)` / `.push(...)`\n    // / \u2026 call becomes a synthetic `$.<field> = <immutable RHS>` assignment so\n    // it flows through the existing UpdateOp coalescer. Expression-position\n    // calls and non-field-path receivers leave the AST untouched and fall\n    // through to the dedicated codegen throws.\n    if (el.type === \"MethodCall\") {\n      const rewrite = tryRewriteMutatorCall(el);\n      if (rewrite.kind === \"rewrite\") el = rewrite.assign;\n    }\n    if (el.type === \"AssignExpr\") {\n      const r = tryLowerAssignSugar(el, ctx, out, flushUpdateOps, tracking.alloc, lowerBlock, out.length === 0);\n      if (r.handled) {\n        ctx = r.ctx;\n        if (r.outPos !== null) validator.markSugarOut(r.outPos);\n        return;\n      }\n      updateBuffer.push(r.bufferOp);\n      return;\n    }\n    if (el.type === \"DeleteStmt\") {\n      if (el.target.type === \"FieldRef\" && el.target.path === \"\") {\n        throw new CodegenError(\n          `Cannot 'delete $' \u2014 bare '$' is the whole document. Use '$ = <newDoc>' to replace it, or 'delete $.<field>' to drop a single field.`,\n          el.pos,\n        );\n      }\n      updateBuffer.push(el);\n      return;\n    }\n    if (el.type === \"LetDecl\") {\n      flushUpdateOps();\n      const direct = detectLookupCall(el.value, ctx);\n      if (direct !== null) {\n        validateLookupShape(el.value);\n        const slot = `${LET_NAMESPACE}.${el.name}`;\n        const stages = lowerLookup(direct, slot, ctx, lowerBlock);\n        for (const s of stages) out.push(s);\n        ctx = extendCtxLets(ctx, el.name, slot);\n        everHadLet = true;\n        return;\n      }\n      const { stages: prologue, rewritten } = extractLookupCalls(el.value, ctx, tracking.alloc, lowerBlock);\n      for (const s of prologue) out.push(s);\n      const stage = lowerLetDecl({ type: \"LetDecl\", name: el.name, value: rewritten, pos: el.pos }, ctx);\n      out.push(stage.set);\n      ctx = stage.ctx;\n      everHadLet = true;\n      return;\n    }\n    flushUpdateOps();\n    ctx = lowerStatementTail(el, i, ctx, out, validator, tracking.alloc, lowerBlock);\n  });\n  flushUpdateOps();\n  if ((everHadLet || tracking.used()) && !shouldSkipTrailingNamespaceUnset(out)) out.push({ $unset: LET_NAMESPACE });\n  return out;\n}\n\n/**\n * Compile a `Pipeline` (a sequence of `;`-separated top-level statements) to\n * an MQL stage array. Each statement is lowered in isolation: a update op\n * chain (`,`-grouped, possibly RAW-split) goes through `generateUpdateFilter`\n * and contributes one or more `$set`/`$unset` stages; an expression must be a\n * stage call/object and contributes exactly one stage.\n *\n * Adjacent update op statements never coalesce \u2014 `;` is a hard boundary, in\n * contrast to `generatePipeline` (the `[\u2026]` form), where consecutive\n * update op elements coalesce through `generateUpdateOpGroups`. This is the\n * core difference between the two pipeline forms.\n *\n * `let` declarations contribute one `$set` stage each and extend the let\n * scope visible to subsequent statements.\n */\nexport function generateImplicitPipeline(\n  p: Pipeline,\n  startCtx: GenerateCtx = EMPTY_CTX,\n  container: ContainerKind = \"top\",\n): unknown[] {\n  const out: unknown[] = [];\n  let ctx: GenerateCtx = startCtx;\n  let everHadLet = false;\n  const validator = makePipelineValidator(container);\n  const tracking = makeSlotTracking();\n\n  p.stmts.forEach((rawStmt, i) => {\n    validator.checkBeforeElement(rawStmt.pos);\n    let stmt: PipelineStmt = rawStmt;\n    // Statement-position mutator rewrite: same logic as `generatePipeline`,\n    // wrapped in a single-op `UpdateFilter` so it routes through the existing\n    // `lowerUpdateFilterWithLookups` path. See the matching block in\n    // `generatePipeline` for the rationale.\n    if (stmt.type === \"MethodCall\") {\n      const rewrite = tryRewriteMutatorCall(stmt);\n      if (rewrite.kind === \"rewrite\") {\n        stmt = { type: \"UpdateFilter\", ops: [rewrite.assign], pos: rewrite.assign.pos };\n      }\n    }\n    if (stmt.type === \"LetDecl\") {\n      const direct = detectLookupCall(stmt.value, ctx);\n      if (direct !== null) {\n        validateLookupShape(stmt.value);\n        const slot = `${LET_NAMESPACE}.${stmt.name}`;\n        const stages = lowerLookup(direct, slot, ctx, lowerBlock);\n        for (const s of stages) out.push(s);\n        ctx = extendCtxLets(ctx, stmt.name, slot);\n        everHadLet = true;\n        return;\n      }\n      const { stages: prologue, rewritten } = extractLookupCalls(stmt.value, ctx, tracking.alloc, lowerBlock);\n      for (const s of prologue) out.push(s);\n      const stage = lowerLetDecl({ type: \"LetDecl\", name: stmt.name, value: rewritten, pos: stmt.pos }, ctx);\n      out.push(stage.set);\n      ctx = stage.ctx;\n      everHadLet = true;\n      return;\n    }\n    if (stmt.type === \"UpdateFilter\") {\n      // Process each op in order, splitting at lookup-bearing ops so the\n      // lookup stages can sit between coalesced $set groups. A `$ = <expr>`\n      // op within the chain clears the let scope (it's a reshape stage), so\n      // the returned ctx may differ from `ctx`. A `$$$.<coll> = \u2026` op records\n      // the terminal `$out` \u2014 once set, the next pipeline statement produces\n      // the \"must be last stage\" error.\n      const result = lowerUpdateFilterWithLookups(stmt, ctx, tracking.alloc, lowerBlock, out.length);\n      for (const s of result.stages) out.push(s);\n      ctx = result.ctx;\n      if (result.terminal !== null) validator.markSugarOut(result.terminal.pos);\n      return;\n    }\n    ctx = lowerStatementTail(stmt as Expr, i, ctx, out, validator, tracking.alloc, lowerBlock);\n  });\n\n  if ((everHadLet || tracking.used()) && !shouldSkipTrailingNamespaceUnset(out)) out.push({ $unset: LET_NAMESPACE });\n  return out;\n}\n\ntype LetLowering = { set: Record<string, unknown>; ctx: GenerateCtx };\n\nfunction lowerLetDecl(decl: LetDecl, ctx: GenerateCtx): LetLowering {\n  if (ctx.pipelineLets?.has(decl.name)) {\n    throw new CodegenError(\n      `\\`let ${decl.name}\\` is already declared earlier in this pipeline. ` +\n        `Re-declaration in the same scope is not allowed \u2014 pick a different name, ` +\n        `or rebind after a reshape stage (\\`$group\\`, \\`$replaceRoot\\`, \u2026).`,\n      decl.pos,\n    );\n  }\n  if (ctx.bindings?.has(decl.name)) {\n    throw new CodegenError(\n      `\\`let ${decl.name}\\` shadows a function-form parameter binding of the same name. ` +\n        `Rename one \u2014 parameter bindings are compile-time constants supplied at call time, ` +\n        `\\`let\\` bindings are per-document values derived from a stage expression; ` +\n        `mixing them under one name would be ambiguous.`,\n      decl.pos,\n    );\n  }\n  const fieldPath = `${LET_NAMESPACE}.${decl.name}`;\n  const value = generateWithCtx(decl.value, ctx);\n  return { set: { $set: { [fieldPath]: value } }, ctx: extendCtxLets(ctx, decl.name, fieldPath) };\n}\n\n/**\n * `$ = <expr>` is an AssignExpr whose LHS is the bare `$` token \u2014 represented\n * in the AST as `FieldRef { path: \"\" }`. Different from `$.<x> = <expr>`\n * (which has a non-empty path) and from any `MemberAccess` chain. This helper\n * recognises the shape; lowering is performed by `lowerReplaceRoot`.\n */\nfunction isReplaceRootAssign(op: AssignExpr): boolean {\n  return op.target.type === \"FieldRef\" && op.target.path === \"\";\n}\n\n/**\n * Lower `$ = <expr>` to a `$replaceWith` stage (MQL's shorthand for\n * `$replaceRoot: { newRoot: <expr> }` \u2014 same runtime, fewer characters).\n *\n * Four variants:\n *   - Compound desugar (`$++`, `$ += 5`, \u2026) is rejected up front: the parser\n *     reuses the same AST node for both `target` and `value.left`, so a\n *     referential-identity check on `BinaryExpr.left === target` catches all of\n *     them without us needing to remember the original surface operator.\n *   - Obviously non-document RHS (`$ = [1,2]`, `$ = 5`, `$ = \"x\"`, direct\n *     `.filter()` lookup) is rejected with an actionable message.\n *   - Direct `$$$.<coll>.find(pred)` RHS becomes `$lookup` (into an internal\n *     `__jsmql.__lookup<N>` slot) followed by `$replaceWith: { $first: \"$<slot>\" }`.\n *     We don't reuse `lowerLookup` because its `.find` form emits an extra\n *     `$set { slot: $first slot }` stage that's wasteful here \u2014 the slot is\n *     discarded by the replace anyway, so `$first` lives inside the\n *     `$replaceWith` instead.\n *   - Anything else: any buried lookups inside the RHS materialise as prologue\n *     stages, then `$replaceWith: <rewritten-RHS>`.\n */\nfunction lowerReplaceRoot(\n  el: AssignExpr,\n  ctx: GenerateCtx,\n  allocSlot: SlotAllocator,\n  lowerBlockFn: SubPipelineLowerer,\n): object[] {\n  if (el.value.type === \"BinaryExpr\" && el.value.left === el.target) {\n    throw new CodegenError(\n      `Cannot use compound assignment / increment on bare '$' \u2014 '$' is the whole document, not a scalar. Use '$ = { ...$, ...overrides }' to merge fields into the root or '$ = <newRoot>' to replace it outright.`,\n      el.pos,\n    );\n  }\n  rejectNonDocumentReplaceRoot(el.value);\n\n  const direct = detectLookupCall(el.value, ctx);\n  if (direct !== null) {\n    validateLookupShape(el.value);\n    if (direct.method === \"filter\") {\n      throw new CodegenError(\n        `Cannot replace root with an array \u2014 '.filter(...)' returns an array. Use '.find(...)' for a single matching doc, or wrap: '$ = { items: $$$.<coll>.filter(...) }'.`,\n        el.value.pos,\n      );\n    }\n    const slot = allocSlot();\n    const pred = translatePredicate(direct, ctx, lowerBlockFn);\n    const from: string | { db: string; coll: string } =\n      direct.db !== undefined ? { db: direct.db, coll: direct.collection } : direct.collection;\n    const stages: object[] = [];\n    if (pred.kind === \"basic\") {\n      stages.push({ $lookup: { from, localField: pred.localField, foreignField: pred.foreignField, as: slot } });\n    } else {\n      stages.push({ $lookup: { from, let: pred.letVars, pipeline: pred.pipeline, as: slot } });\n    }\n    stages.push({ $replaceWith: { $first: `$${slot}` } });\n    return stages;\n  }\n\n  const { stages: prologue, rewritten } = extractLookupCalls(el.value, ctx, allocSlot, lowerBlockFn);\n  const out: object[] = [...prologue];\n  out.push({ $replaceWith: generateWithCtx(rewritten, ctx) });\n  return out;\n}\n\n/**\n * Reject RHS shapes that the user wouldn't have meant as a new document root.\n * Permissive by design \u2014 anything that *might* be a document (FieldRef,\n * MemberAccess, ObjectLiteral, OperatorCall, MethodCall, BinaryExpr, ternaries,\n * `$let`-style helpers) passes through; MongoDB validates document-shape at\n * runtime if our static check missed something.\n */\nfunction rejectNonDocumentReplaceRoot(value: Expr): void {\n  if (value.type === \"ArrayLiteral\") {\n    throw new CodegenError(\n      `Cannot replace root with an array. Use '.find(...)' for a single doc, or wrap: '$ = { items: [...] }'.`,\n      value.pos,\n    );\n  }\n  const literalKind =\n    value.type === \"NumberLiteral\"\n      ? \"number\"\n      : value.type === \"BigIntLiteral\"\n        ? \"bigint\"\n        : value.type === \"StringLiteral\"\n          ? \"string\"\n          : value.type === \"BooleanLiteral\"\n            ? \"boolean\"\n            : value.type === \"NullLiteral\"\n              ? \"null\"\n              : value.type === \"RegexLiteral\"\n                ? \"regex\"\n                : null;\n  if (literalKind !== null) {\n    throw new CodegenError(\n      `Cannot replace root with a ${literalKind} \u2014 the new root must be a document. Did you mean to wrap it: '$ = { value: ... }'?`,\n      value.pos,\n    );\n  }\n}\n\ntype LambdaNode = Extract<Expr, { type: \"Lambda\" }>;\n\n/**\n * `$$ = <expr>` is an AssignExpr whose LHS is the `$$` token (the current\n * document stream) \u2014 represented in the AST as `CollectionRef`. Sister shape\n * to `$ = <expr>` (single-doc replacement \u2192 `$replaceWith`); `$$ = <expr>`\n * replaces the *stream* and lowers to either a `$match` (narrow) or\n * `$limit: 0` + `$unionWith` (switch source).\n */\nfunction isReplaceStreamAssign(op: AssignExpr): boolean {\n  return op.target.type === \"CollectionRef\";\n}\n\n/**\n * Lower `$$ = <expr>` to the stage(s) it represents.\n *\n * Two RHS shapes are accepted; anything else throws an actionable error:\n *\n *   - `$$.filter(<lambda>)`            \u2192 `[{ $match: <translated> }]`\n *   - `$$$.<coll>.filter(<lambda>)`    \u2192 `[{ $limit: 0 },\n *                                          { $unionWith: { coll, pipeline: [{ $match }] } }]`\n *\n * Inside both shapes the lambda parameter IS the document being matched;\n * `param.x` rewrites to a bare `FieldRef(\"x\")` and `$.<field>` references\n * are rejected with a \"use the lambda parameter\" hint. This mirrors the\n * facet form's convention \u2014 adding a second spelling for the current doc\n * would only invite drift.\n *\n * `clearLets` distinguishes the two outcomes for the caller: the source-\n * switch form drops the outer collection entirely, so any prior `let`\n * binding becomes unreadable; the narrow form preserves the stream and\n * its bindings.\n */\nfunction lowerReplaceStream(\n  el: AssignExpr,\n  outerCtx: GenerateCtx,\n  lowerBlockFn: SubPipelineLowerer,\n  allocSlot: SlotAllocator,\n  isFirstStage: boolean,\n): { stages: object[]; clearLets: boolean } {\n  if (el.value.type === \"BinaryExpr\" && el.value.left === el.target) {\n    throw new CodegenError(\n      `Cannot use compound assignment / increment on '$$' \u2014 '$$' is the document stream, not a scalar. Use '$$ = $$.filter(<predicate>)' to narrow the stream or '$$ = $$$.<coll>.filter(<predicate>)' to switch source.`,\n      el.pos,\n    );\n  }\n  const v = el.value;\n  // `$$ = [{ <key>: $$.reduce(\u2026), \u2026 }];` \u2014 the JS-faithful wrap pattern for\n  // folding the stream into a single-doc summary. `.reduce` is NOT a chain\n  // method on `$$` (would break the \"stream is always an array\" invariant);\n  // this wrap is the only legal way to consume a reduce result back into\n  // the stream. See docs/specs/stream-methods.md.\n  // Dict-build runs FIRST because its shape (single computed key on `d.<path>`)\n  // overlaps with the object-reducer detector below, which would otherwise\n  // throw \"computed keys not supported\" before we get a chance.\n  const dictBuild = detectDictBuildWrap(v);\n  if (dictBuild !== null) {\n    return { stages: lowerDictBuildWrap(dictBuild), clearLets: true };\n  }\n  const reduceWrap = detectReduceWrap(v);\n  if (reduceWrap !== null) {\n    return { stages: lowerReduceWrap(reduceWrap), clearLets: true };\n  }\n  // `$$ = $$.reduce((acc, d) => acc.concat(d.<path>), []);` \u2014 the\n  // array-returning reducer form. A `[]`-seeded reducer already returns an\n  // array (a stream), so it's assigned unbracketed. Lowers to `$match` (when\n  // the reducer is a `cond ? concat : acc` ternary) + `$replaceWith` (when the\n  // projection is a field path). Sibling to the `$group`-shaped wrap above;\n  // different lowering family. The legacy bracketed form throws (see\n  // `detectArrayReducerWrap`).\n  const arrayReducer = detectArrayReducerWrap(v);\n  if (arrayReducer !== null) {\n    return { stages: lowerArrayReducerWrap(arrayReducer, outerCtx, lowerBlockFn), clearLets: true };\n  }\n  const chain = collectStreamChain(v);\n  if (chain.root.type === \"CollectionRef\" && chain.methods.length > 0) {\n    return lowerChainOnStream(chain.methods, outerCtx, lowerBlockFn, allocSlot, v);\n  }\n  if (chain.methods.length > 0) {\n    const target = extractLookupTarget(chain.root, outerCtx);\n    if (target !== null) {\n      return lowerChainOnCollection(chain.methods, target, outerCtx, lowerBlockFn, allocSlot, v);\n    }\n  }\n  // Array-literal RHSes that aren't reduce-wraps:\n  //   - `$$ = []` \u2192 `[{ $limit: 0 }]` (drop all docs; pre-1.0 sugar item #2)\n  //   - `$$ = [{...}, {...}]` at stage 0 \u2192 `[{ $documents: [...] }]`\n  //     (literal-doc seed; MongoDB requires $documents to be the first stage)\n  //   - `$$ = [{...}, {...}]` mid-pipeline \u2192 throw, naming `$$.push(...)` as\n  //     the right tool for appending docs to an existing stream.\n  if (v.type === \"ArrayLiteral\") {\n    if (v.elements.length === 0) {\n      return { stages: [{ $limit: 0 }], clearLets: false };\n    }\n    if (isFirstStage) {\n      const docs = extractDocumentsLiteral(v);\n      if (docs !== null) {\n        return { stages: [{ $documents: docs }], clearLets: true };\n      }\n    } else if (isAllObjectLiteralElements(v)) {\n      throw new CodegenError(\n        `'$$ = [<docs>]' is only valid as the first stage of a pipeline ('$documents' must be at the head per MongoDB). To append documents to an existing stream, use '$$.push({...}, {...}, \u2026)' instead, which lowers to '$unionWith'.`,\n        v.pos,\n      );\n    }\n  }\n  rejectInvalidReplaceStream(v, outerCtx);\n}\n\n/**\n * Extract a literal-document list for the `$$ = [{...}, {...}]` \u2192\n * `$documents` sugar. Returns null if any element isn't a literal object \u2014\n * then the caller falls through to the reduce-wrap / \"use push\" error path.\n */\nfunction extractDocumentsLiteral(arr: Extract<Expr, { type: \"ArrayLiteral\" }>): unknown[] | null {\n  const out: unknown[] = [];\n  for (const el of arr.elements) {\n    if (el.type !== \"ObjectLiteral\") return null;\n    out.push(generateWithCtx(el, EMPTY_CTX));\n  }\n  return out;\n}\n\nfunction isAllObjectLiteralElements(arr: Extract<Expr, { type: \"ArrayLiteral\" }>): boolean {\n  for (const el of arr.elements) {\n    if (el.type !== \"ObjectLiteral\") return false;\n  }\n  return true;\n}\n\n/**\n * Lower a chain `$$.<m1>(...).<m2>(...)\u2026` into stages on the outer pipeline.\n *\n * The first method may be `.filter(<lambda>)` \u2014 that produces a `$match`\n * stage exactly as before (predicate translated in the outer ctx so prior\n * `let` bindings resolve). Any subsequent method, or a non-`.filter` first\n * method, is dispatched through the stream-method registry. Unknown method\n * names throw an actionable error listing the registered alternatives.\n */\nfunction lowerChainOnStream(\n  methods: MethodCallNode[],\n  outerCtx: GenerateCtx,\n  lowerBlockFn: SubPipelineLowerer,\n  allocSlot: SlotAllocator,\n  rhs: Expr,\n): { stages: object[]; clearLets: boolean } {\n  const stages: object[] = [];\n  const clearLets = applyStreamMethods(methods, stages, outerCtx, lowerBlockFn, allocSlot, rhs);\n  return { stages, clearLets };\n}\n\n/**\n * Apply a `$$`-rooted method chain onto `target`, appending each method's\n * stages and using `target` itself as the `prevStages` view (and the\n * `replacesPreviousStage` pop target).\n *\n * Shared by two callers that differ only in *which* buffer they pass:\n *   - `lowerChainOnStream` (the `$$ = $$.<chain>` assignment form) passes a\n *     fresh local array, so the chain composes only against itself.\n *   - `lowerStatementTail` (the bare `$$.<chain>;` statement form) passes the\n *     live pipeline `out`, so a stage-coupled method (`.toReversed`) flips the\n *     `$sort` emitted just before it \u2014 whether that `$sort` came from an\n *     earlier method in this chain OR an earlier *statement*. That's what makes\n *     `$$.toSorted(c).toReversed();` and `$$.toSorted(c); $$.toReversed();`\n *     lower identically.\n *\n * The first method may be `.filter(<lambda>)` \u2192 a `$match` stage (predicate\n * translated in `ctx` so prior `let` bindings resolve). Any subsequent method,\n * or a non-`.filter` first method, dispatches through the stream-method\n * registry; unknown names throw an actionable error. Returns whether any\n * method cleared the `let` scope (the caller applies `clearCtxLets`).\n */\nfunction applyStreamMethods(\n  methods: MethodCallNode[],\n  target: object[],\n  ctx: GenerateCtx,\n  lowerBlockFn: SubPipelineLowerer,\n  allocSlot: SlotAllocator,\n  rhs: Expr,\n): boolean {\n  let clearLets = false;\n  let i = 0;\n  if (methods[0].method === \"filter\") {\n    const m = methods[0];\n    if (m.args.length !== 1 || m.args[0].type !== \"Lambda\") {\n      rejectInvalidReplaceStream(rhs, ctx);\n    }\n    const matchStages = lowerStreamFilterPredicate(m.args[0] as LambdaNode, ctx, lowerBlockFn);\n    target.push(...matchStages);\n    i = 1;\n  }\n  for (; i < methods.length; i++) {\n    const m = methods[i];\n    const def = lookupStreamMethod(m.method);\n    if (def === null) {\n      throw unknownStreamMethod(m, \"$$\");\n    }\n    def.validate(m.args, m.pos);\n    const result = def.lower(m.args, ctx, m.pos, lowerBlockFn, target, allocSlot, false);\n    if (result.replacesPreviousStage) target.pop();\n    target.push(...result.stages);\n    if (result.clearLets) clearLets = true;\n  }\n  return clearLets;\n}\n\n/**\n * Lower a chain `$$$.<coll>.<m1>(...).<m2>(...)\u2026` on the RHS of `$$ = \u2026`.\n *\n * **Two lowering families** depending on whether the chain head's\n * `.filter(<pred>)` correlates against the outer document:\n *\n *   - **Source switch (`$limit:0` + `$unionWith`).** When the predicate is\n *     a flat foreign-collection scan \u2014 no `$.<field>` references \u2014 the\n *     chain runs as an independent sub-pipeline. The outer stream is\n *     dropped (`$limit:0`) and replaced by docs flowing out of the\n *     `$unionWith.pipeline:` body. Default behaviour.\n *\n *   - **`$lookup`-pivot (`$lookup` + `$unwind` + `$replaceWith`).** When\n *     the predicate references the outer doc (`$.<field>`) \u2014 i.e. the\n *     match is *per-outer-doc* \u2014 jsmql can't use `$unionWith` because that\n *     stage has no `let:` slot. Instead the chain lowers to a `$lookup`\n *     (basic-form when the predicate is a single `===`, pipeline-form\n *     otherwise) that joins each outer doc to its matching foreign docs,\n *     followed by `$unwind` to explode the array and `$replaceWith` to\n *     make the matched doc the new root. Subsequent chain methods extend\n *     the lookup's pipeline body (so `.toSorted` / `.slice` / etc. apply\n *     before `$unwind`).\n *\n * The dispatch happens at the predicate level: `predicateReferencesOuterDoc`\n * runs `extractLetsFromExpr` to see whether any `$.<field>` paths would be\n * hoisted as `$lookup.let` vars; if any, the pivot path takes over.\n *\n * When the chain is just `.filter(o => true)` (vacuous, no outer refs and\n * no chain methods) the inner pipeline is empty and the short-form\n * `$unionWith` shape is emitted \u2014 same as before this chain walker existed.\n */\nfunction lowerChainOnCollection(\n  methods: MethodCallNode[],\n  target: { db?: string; collection: string },\n  outerCtx: GenerateCtx,\n  lowerBlockFn: SubPipelineLowerer,\n  allocSlot: SlotAllocator,\n  rhs: Expr,\n): { stages: object[]; clearLets: boolean } {\n  // $lookup-pivot dispatch: when the head's `.filter(<pred>)` references\n  // outer-doc fields, switch lowering families.\n  if (\n    methods[0].method === \"filter\" &&\n    methods[0].args.length === 1 &&\n    methods[0].args[0].type === \"Lambda\" &&\n    predicateReferencesOuterDoc(methods[0].args[0] as LambdaNode, outerCtx)\n  ) {\n    return lowerLookupPivot(methods, target, outerCtx, lowerBlockFn, allocSlot);\n  }\n  const innerCtx = freshSubPipelineCtx(outerCtx);\n  const inner: object[] = [];\n  let i = 0;\n  if (methods[0].method === \"filter\") {\n    const m = methods[0];\n    if (m.args.length !== 1 || m.args[0].type !== \"Lambda\") {\n      rejectInvalidReplaceStream(rhs, outerCtx);\n    }\n    const matchStages = lowerStreamFilterPredicate(m.args[0] as LambdaNode, innerCtx, lowerBlockFn);\n    inner.push(...matchStages);\n    i = 1;\n  }\n  for (; i < methods.length; i++) {\n    const m = methods[i];\n    const def = lookupStreamMethod(m.method);\n    if (def === null) {\n      throw unknownStreamMethod(m, \"$$$.<coll>\");\n    }\n    def.validate(m.args, m.pos);\n    const result = def.lower(m.args, innerCtx, m.pos, lowerBlockFn, inner, allocSlot, true);\n    if (result.replacesPreviousStage) inner.pop();\n    inner.push(...result.stages);\n  }\n  const from: string | { db: string; coll: string } =\n    target.db !== undefined ? { db: target.db, coll: target.collection } : target.collection;\n  const stages: object[] = [{ $limit: 0 }];\n  if (inner.length === 0) {\n    if (typeof from === \"string\") {\n      stages.push({ $unionWith: from });\n    } else {\n      stages.push({ $unionWith: { coll: from } });\n    }\n  } else {\n    stages.push({ $unionWith: { coll: from, pipeline: inner } });\n  }\n  return { stages, clearLets: true };\n}\n\n/**\n * Lower a `$$ = $$$.<coll>.filter(<correlatedPred>).<chain>;` source-switch\n * whose predicate references the outer document. Emits:\n *\n *   1. `$lookup` joining each outer doc to its matching foreign docs.\n *      - Basic form (`{ from, localField, foreignField, as }`) when the\n *        predicate is a single `===` between a foreign-path and a\n *        `$.<path>` and there are no chain methods after `.filter`.\n *      - Pipeline form (`{ from, let, pipeline, as }`) otherwise \u2014 `let`\n *        threads the outer-doc fields through, and chain methods extend\n *        the pipeline body before the array is returned.\n *   2. `$unwind` to explode the per-outer-doc array of matches.\n *   3. `$replaceWith` to make each matched foreign doc the new stream root.\n *\n * The result is a stream pivoted onto the foreign collection, where every\n * row was *correlated* against an outer doc (vs `$unionWith`, which would\n * just append a flat scan). Outer docs with no match are dropped by\n * `$unwind`'s default behaviour \u2014 the user can keep them by writing the\n * explicit `$.matched = $$$.coll.filter(...); $unwind($.matched, true); $ = $.matched`\n * chain when they need `preserveNullAndEmptyArrays`.\n *\n * `clearLets: true` because the trailing `$replaceWith` reshapes the doc,\n * dropping any outer `let` bindings the surrounding pipeline had.\n */\nfunction lowerLookupPivot(\n  methods: MethodCallNode[],\n  target: { db?: string; collection: string },\n  outerCtx: GenerateCtx,\n  lowerBlockFn: SubPipelineLowerer,\n  allocSlot: SlotAllocator,\n): { stages: object[]; clearLets: boolean } {\n  const filterMethod = methods[0];\n  const restMethods = methods.slice(1);\n  const lambda = filterMethod.args[0] as LambdaNode;\n  const slot = allocSlot();\n  const from: string | { db: string; coll: string } =\n    target.db !== undefined ? { db: target.db, coll: target.collection } : target.collection;\n  let lookupStage: object;\n  if (restMethods.length === 0) {\n    // No chain methods after `.filter` \u2014 basic form is fine when the\n    // predicate qualifies. `translatePredicate` handles both basic and\n    // pipeline forms; we just write whichever it returns.\n    const fakeCall: LookupCall = {\n      pos: filterMethod.pos,\n      callPos: filterMethod.pos,\n      db: target.db,\n      collection: target.collection,\n      method: \"filter\",\n      lambda,\n    };\n    const pred = translatePredicate(fakeCall, outerCtx, lowerBlockFn);\n    if (pred.kind === \"basic\") {\n      lookupStage = { $lookup: { from, localField: pred.localField, foreignField: pred.foreignField, as: slot } };\n    } else {\n      lookupStage = { $lookup: { from, let: pred.letVars, pipeline: pred.pipeline, as: slot } };\n    }\n  } else {\n    // Chain methods need a pipeline-form lookup so their stages can extend\n    // the sub-pipeline body.\n    const { letVars, pipelineBody } = buildPipelineFormPredicate(lambda, outerCtx, lowerBlockFn);\n    const innerCtx = freshSubPipelineCtx(outerCtx);\n    for (const m of restMethods) {\n      const def = lookupStreamMethod(m.method);\n      if (def === null) {\n        throw unknownStreamMethod(m, \"$$$.<coll>\");\n      }\n      def.validate(m.args, m.pos);\n      const result = def.lower(m.args, innerCtx, m.pos, lowerBlockFn, pipelineBody, allocSlot, true);\n      if (result.replacesPreviousStage) pipelineBody.pop();\n      pipelineBody.push(...result.stages);\n    }\n    lookupStage = { $lookup: { from, let: letVars, pipeline: pipelineBody, as: slot } };\n  }\n  return { stages: [lookupStage, { $unwind: `$${slot}` }, { $replaceWith: `$${slot}` }], clearLets: true };\n}\n\nfunction unknownStreamMethod(m: MethodCallNode, receiver: string): CodegenError {\n  // Methods that return a single element in JS \u2014 deliberately rejected because\n  // pipelines are arrays. The error names the explicit alternative so the user\n  // doesn't have to dig for it.\n  if (m.method === \"find\" || m.method === \"findLast\" || m.method === \"at\") {\n    const alt = m.method === \"at\" ? `'${receiver}.slice(n, n + 1)'` : `'${receiver}.filter(<pred>).slice(0, 1)'`;\n    const findHint =\n      receiver === \"$$$.<coll>\"\n        ? ` (For replacing the current document with a single matched foreign doc, write '$ = $$$.<coll>.find(<pred>)' instead \u2014 that's a separate lookup form.)`\n        : \"\";\n    return new CodegenError(\n      `'.${m.method}(...)' is not allowed in a chain on '${receiver}' \u2014 '.${m.method}' returns a single element in JS, but pipelines are arrays. ` +\n        `Use ${alt} for the equivalent \"first match\" / \"n-th\" shape.${findHint}`,\n      m.pos,\n    );\n  }\n  // `.reduce` is rejected as a chain method for the same reason \u2014 in JS,\n  // `arr.reduce(...)` returns a scalar / object / array depending on the\n  // reducer. Assigning a non-array result directly to `$$` would break the\n  // \"stream is always an array of docs\" invariant. The user must wrap.\n  if (m.method === \"reduce\") {\n    return new CodegenError(\n      `'.reduce(...)' is not a chain method on '${receiver}' \u2014 in JS '.reduce' collapses an array to a single value, but '${receiver}' must stay a stream of documents. Wrap the reduce result into a stream-shaped RHS:\\n` +\n        `  \u2022 Scalar reducer:  '$$ = [{ <key>: $$.reduce((acc, d) => \u2026, <literal-init>) }];' \u2014 each entry becomes a '$group' accumulator; output is a single-doc stream of your named keys.\\n` +\n        `  \u2022 Object reducer:  '$$ = [$$.reduce((acc, d) => ({ ...acc, <key1>: <expr1>, <key2>: <expr2> }), { <key1>: <init1>, <key2>: <init2> })];' \u2014 same MQL output as the scalar form, keyed accumulators declared inline.\\n` +\n        `  \u2022 Array reducer:   '$$ = $$.reduce((acc, d) => (<cond> ? acc.concat(d.<field>) : acc), []);' \u2014 a '[]'-seeded reducer already returns a stream, so assign it directly (no '[ ]'); lowers to '$match' (when the body is a ternary) + '$replaceWith: \"$<field>\"'. Each input doc that passes <cond> becomes its <field> sub-doc.\\n` +\n        `Pick the wrap shape that matches what your reducer would return in plain JS.`,\n      m.pos,\n    );\n  }\n  const names = streamMethodNames();\n  // The bare `$$` stream also accepts `.push(...)` as a statement-level method\n  // (\u2192 `$unionWith`); it isn't a chain method, but naming it in the suggestion\n  // set catches `.pop` / `.shift` mix-ups that a JS dev reaches for.\n  const isStream = receiver === \"$$\";\n  const hint = didYouMean(m.method, isStream ? [\"filter\", \"push\", ...names] : [\"filter\", ...names], (s) => `.${s}`);\n  const list = names.length > 0 ? names.map((n) => `.${n}`).join(\", \") : \"(none yet)\";\n  const pushNote = isStream ? ` ('.push(...)' appends documents as a statement \u2192 $unionWith.)` : \"\";\n  return new CodegenError(\n    `'.${m.method}(...)' is not a chainable stream method on '${receiver}'.${hint} ` +\n      `The chain head may be '.filter(<predicate>)'; subsequent methods must come from the stream-method registry: ${list}.${pushNote}`,\n    m.pos,\n  );\n}\n\n/**\n * Lower a detected `$$ = $$.reduce((acc, d) => \u2026, [])` array-returning\n * reducer into `$match` (when the body is `cond ? acc.concat(...) : acc`)\n * + `$replaceWith` (when the projection is `d.<path>`; omitted when the\n * reducer concats bare `d` \u2014 the docs flow through unchanged).\n *\n * The condition translates through the same `lowerStreamFilterPredicate`\n * engine `.filter` uses; the condition's `$.<field>` refs are rejected\n * with the standard \"use the lambda parameter\" hint.\n */\nfunction lowerArrayReducerWrap(\n  wrap: ArrayReducerWrap,\n  outerCtx: GenerateCtx,\n  lowerBlockFn: SubPipelineLowerer,\n): object[] {\n  const stages: object[] = [];\n  if (wrap.condition !== null) {\n    // Synthesise a single-param Lambda from (dParam, condition) so the\n    // existing predicate-translation engine handles the body unchanged.\n    // `pos` carries the lambda's original pos for error reporting.\n    const fakeLambda: LambdaNode = { type: \"Lambda\", params: [wrap.dParam], body: wrap.condition, pos: wrap.lambdaPos };\n    stages.push(...lowerStreamFilterPredicate(fakeLambda, outerCtx, lowerBlockFn));\n  }\n  if (wrap.project.kind === \"field\") {\n    stages.push({ $replaceWith: `$${wrap.project.path}` });\n  }\n  return stages;\n}\n\nfunction lowerStreamFilterPredicate(\n  lambda: LambdaNode,\n  predicateCtx: GenerateCtx,\n  lowerBlockFn: SubPipelineLowerer,\n): object[] {\n  if (lambda.params.length !== 1) {\n    throw new CodegenError(\n      `'.filter(<predicate>)' on the RHS of '$$ = \u2026' must take exactly one parameter \u2014 write '.filter(o => \u2026)' (the param name is your choice). The param represents each document.`,\n      lambda.pos,\n    );\n  }\n  // Shared expr-or-block predicate lowering (see `lowerLambdaPredicate`). The\n  // stream filter already runs in the right ctx, so `freshCtx` is identity. A\n  // `$.<field>` reference (captured as a non-empty `letVars`) is rejected \u2014 the\n  // lambda parameter IS the document being matched.\n  return lowerLambdaPredicate(lambda, predicateCtx, lowerBlockFn, {\n    freshCtx: (ctx) => ctx,\n    onLocalRef: rejectLocalRefInStreamFilter,\n    missingBody: () => {\n      throw new CodegenError(\n        `'.filter(<predicate>)' lambda is missing a body \u2014 internal parser bug; please report.`,\n        lambda.pos,\n      );\n    },\n  });\n}\n\nfunction rejectLocalRefInStreamFilter(letVars: Record<string, string>, param: string, pos: number): never {\n  const sample = Object.values(letVars)[0];\n  const samplePath = sample.replace(/^\\$+/, \"\");\n  throw new CodegenError(\n    `'$.<field>' inside the '.filter(<predicate>)' of '$$ = \u2026' is not supported \u2014 use the lambda parameter (e.g. '${param}.${samplePath}') to reference each document. Inside this filter, the lambda parameter IS the document being matched.`,\n    pos,\n  );\n}\n\nfunction rejectInvalidReplaceStream(value: Expr, ctx: GenerateCtx): never {\n  if (value.type === \"ArrayLiteral\") {\n    // ArrayLiteral handling has moved up into `lowerReplaceStream` (empty \u2192 $limit:0,\n    // first-stage literal-doc list \u2192 $documents, non-first-stage rejection). The\n    // only ArrayLiteral RHSes that reach this rejection branch are ones that\n    // pass the reduce-wrap detectors *and* fall outside the new sugar \u2014 i.e.\n    // a single-doc-shaped array element that didn't match any wrap form. Point\n    // at the three reduce-wrap patterns explicitly.\n    throw new CodegenError(\n      `'$$ = [<expr>]' didn't match any supported wrap pattern. Recognised shapes: ` +\n        `'$$ = [{ <key>: $$.reduce(\u2026, <literal-init>), \u2026 }]' (scalar accumulators \u2192 '$group' + '$replaceWith'), ` +\n        `'$$ = [$$.reduce((acc, d) => ({ ...acc, <key>: <expr>, \u2026 }), { <key>: <init>, \u2026 })]' (object-returning reducer, same lowering), ` +\n        `'$$ = [$$.reduce((acc, d) => ({ ...acc, [d.<k>]: <expr>, \u2026 }), {})]' (dict-build reducer \u2192 '$group' + '\\$arrayToObject'), ` +\n        `or '$$ = [$$.reduce((acc, d) => (<cond> ? acc.concat(d.<field>) : acc), [])]' (array-returning reducer \u2192 '$match' + '$replaceWith'). ` +\n        `For a literal-doc seeder at stage 0, use '$$ = [{...}, {...}]' (lowers to '$documents'). To append docs mid-pipeline, use '$$.push({...}, {...}, \u2026)'.`,\n      value.pos,\n    );\n  }\n  if (value.type === \"TernaryExpr\") {\n    throw new CodegenError(\n      `'$$ = <ternary>' (conditional stream branching) is not yet supported [DEF-001]. The RHS of '$$ = \u2026' must be '$$.filter(<predicate>)' (narrow the current stream) or '$$$.<coll>.filter(<predicate>)' (switch source to another collection). See docs/DEFERRED.md.`,\n      value.pos,\n    );\n  }\n  if (value.type === \"MethodCall\") {\n    const onCollection = value.object.type === \"CollectionRef\";\n    const onDatabase = extractLookupTarget(value.object, ctx) !== null;\n    if (onCollection || onDatabase) {\n      const hint = didYouMean(value.method, [\"filter\"], (s) => `.${s}`);\n      const recv = onCollection ? \"$$\" : \"$$$.<coll>\";\n      const intent = onCollection ? \"narrow the current stream\" : \"switch source to another collection\";\n      throw new CodegenError(\n        `'$$ = \u2026' RHS supports only '${recv}.filter(<predicate>)' \u2014 '.${value.method}(...)' is not allowed here.${hint} ` +\n          `Use '${recv}.filter(<predicate>)' to ${intent}, ` +\n          `or write '$ = $$$.<coll>.find(<predicate>)' if you meant to replace each document with a single matching foreign doc.`,\n        value.pos,\n      );\n    }\n  }\n  if (value.type === \"CollectionRef\" || value.type === \"DatabaseRef\") {\n    throw new CodegenError(\n      `'$$ = \u2026' RHS must call '.filter(<predicate>)'. Write '$$.filter(o => \u2026)' to narrow the current stream or '$$$.<coll>.filter(o => \u2026)' to switch source.`,\n      value.pos,\n    );\n  }\n  throw new CodegenError(\n    `'$$ = \u2026' RHS must be '$$.filter(<predicate>)' (narrow the current stream) or '$$$.<coll>.filter(<predicate>)' (switch source to another collection).`,\n    value.pos,\n  );\n}\n\n/**\n * Emit the single source stage for a `$$.indexStats()` / `$$$$.currentOp(...)` /\n * `$$$$.shardedDataDistribution()` diagnostic call. The options object (when\n * present) lowers through the same `generateStageBody` path every other stage\n * body uses \u2014 all nine diagnostics declare `subPipelineFields: []`, so it's a\n * plain recursive object codegen. No options \u2192 an empty `{}` body.\n */\nfunction lowerSystemStageStmt(call: SystemStageCall, ctx: GenerateCtx): object {\n  const body = call.optionsExpr === null ? {} : generateStageBody(call.stageName, call.optionsExpr, ctx);\n  return { [call.stageName]: body };\n}\n\ntype StageLowering = { stage: Record<string, unknown>; ctx: GenerateCtx };\n\nfunction lowerStageElement(el: ArrayElement, index: number, ctx: GenerateCtx): StageLowering {\n  const stage = asStageShape(el);\n  if (!stage) {\n    const pos = (el as { pos?: number }).pos ?? 0;\n    throw new CodegenError(formatNotAStageError(el, index), pos);\n  }\n  const body = generateStageBody(stage.name, stage.body, ctx);\n  const nextCtx = RESHAPE_CLEARING_STAGES.has(stage.name) ? clearCtxLets(ctx, stage.name) : ctx;\n  return { stage: { [stage.name]: body }, ctx: nextCtx };\n}\n\nfunction generateStageBody(stageName: string, body: Expr, ctx: GenerateCtx): unknown {\n  // Body-shape validation (literal-gated; see stage-validation.ts). Runs for\n  // every user-written stage body before lowering.\n  validateStageBody(stageName, body);\n  // $match: ObjectLiteral body \u2192 raw query document (also the `$expr` escape\n  // hatch). Expression body \u2192 query-language translation with $expr fallback\n  // for residual sub-expressions. Residual lowering re-enters codegen with the\n  // pipeline ctx so a let referenced inside the residual still resolves to its\n  // namespace field path.\n  if (stageName === \"$match\") {\n    if (body.type === \"ObjectLiteral\") {\n      return generateBodyObject(body, stageName, ctx);\n    }\n    const t = translateMatchBody(body, { bindings: ctx.bindings });\n    // `?? {}` is defensive \u2014 translateMatchBody never yields empty-query +\n    // null-residual (a vacuous body lands in the residual as `$expr`).\n    return mergeTranslatedQuery(t, ctx) ?? {};\n  }\n\n  // $unwind: its body is field-path DATA, not an expression \u2014 a bare path\n  // string (\"$items\") or { path: \"$items\", includeArrayIndex, preserveNull... }.\n  // The leading `$` is the path the user wants, NOT a string to protect with\n  // $literal (that wrap is for expression contexts). validateUnwind already\n  // enforced the `$`-prefix, so emit the path raw via fieldPathString.\n  if (stageName === \"$unwind\") {\n    const pathCtx = { ...ctx, fieldPathString: true };\n    if (body.type === \"ObjectLiteral\") return generateBodyObject(body, stageName, pathCtx);\n    return generateWithCtx(body, pathCtx);\n  }\n\n  // Other stages: if the body is an object literal, walk its entries so we\n  // can spot sub-pipeline slots; otherwise generate directly.\n  if (body.type === \"ObjectLiteral\") {\n    return generateBodyObject(body, stageName, ctx);\n  }\n  return generateWithCtx(body, ctx);\n}\n\n/**\n * Walk a stage's object-literal body, recursing into sub-pipeline slots\n * (configured per-stage in STAGES). Non-pipeline slots fall through to the\n * normal expression codegen with the parent's ctx (so lets are visible in\n * stage-body expressions). Sub-pipelines get a fresh empty ctx \u2014 outer lets\n * do not cross sub-pipeline boundaries.\n */\nfunction generateBodyObject(\n  body: Expr & { type: \"ObjectLiteral\" },\n  stageName: string,\n  ctx: GenerateCtx,\n): Record<string, unknown> {\n  const stage = lookupStage(stageName)!;\n  const allValuesArePipelines = stage.subPipelineFields.includes(\"*\");\n  const pipelineSlot = new Set(stage.subPipelineFields);\n\n  const out: Record<string, unknown> = {};\n  for (const entry of body.entries) {\n    if (entry.type !== \"KeyValueEntry\") {\n      throw new CodegenError(`Spread entries are not allowed in ${stageName} body`, entry.pos);\n    }\n    if (entry.key.kind !== \"static\") {\n      throw new CodegenError(`Computed keys are not allowed in ${stageName} body`, entry.pos);\n    }\n    const key = entry.key.name;\n    const isPipelineSlot = allValuesArePipelines || pipelineSlot.has(key);\n    if (isPipelineSlot && isPipelineAst(entry.value)) {\n      // Sub-pipelines run in a fresh scope. Outer lets do not cross; function-\n      // form parameter bindings do (they're compile-time constants).\n      out[key] = generatePipelineWithCtx(entry.value, freshSubPipelineCtx(ctx), containerKindFor(stageName));\n      continue;\n    }\n    // Accumulator-context gate (Wave 5 #22 + #41).\n    //\n    // - `$group` field-value slots (every key except `_id`) \u2192 \"group\" ctx,\n    //   so accumulator-only operators ($addToSet, $push, $bottom*, etc.)\n    //   pass the codegen gate; window ops still throw.\n    // - `$setWindowFields.output[<key>]` \u2192 \"window-output\" ctx, both\n    //   accumulator-only AND window-only operators (e.g. $rank,\n    //   $denseRank) pass.\n    // - `$bucket` / `$bucketAuto` `output` key's nested values: same as\n    //   $group field values \u2014 accumulator context.\n    const nestedScope = NESTED_ACCUMULATOR_OUTPUT[stageName];\n    if (nestedScope !== undefined && key === \"output\" && entry.value.type === \"ObjectLiteral\") {\n      out[key] = generateNestedAccumulatorObject(entry.value, ctx, nestedScope);\n      continue;\n    }\n    const slotCtx = accumulatorCtxFor(stageName, key, ctx);\n    out[key] = generateWithCtx(entry.value, slotCtx);\n  }\n  return out;\n}\n\n/**\n * Stages whose `output` slot is an object whose VALUES are accumulator (or,\n * for `$setWindowFields`, window) expressions. The level of indirection\n * matters: `$bucket({ output: { count: $sum(1) } })` vs `$group({ count:\n * $sum(1) })` \u2014 same accumulator semantics, different nesting depth.\n */\nconst NESTED_ACCUMULATOR_OUTPUT: Record<string, \"group\" | \"window-output\"> = {\n  $bucket: \"group\",\n  $bucketAuto: \"group\",\n  $setWindowFields: \"window-output\",\n};\n\n/** For `$group` field-value slots (other than `_id`). */\nfunction accumulatorCtxFor(stageName: string, key: string, ctx: GenerateCtx): GenerateCtx {\n  if (stageName === \"$group\" && key !== \"_id\") {\n    return { ...ctx, accumulatorContext: \"group\" };\n  }\n  return ctx;\n}\n\n/**\n * Walk an object whose direct entries are accumulator expressions \u2014 used for\n * `$bucket.output`, `$bucketAuto.output`, and `$setWindowFields.output`. Each\n * entry's value is generated with the appropriate `accumulatorContext`. The\n * surrounding object literal preserves order.\n */\nfunction generateNestedAccumulatorObject(\n  body: Expr & { type: \"ObjectLiteral\" },\n  ctx: GenerateCtx,\n  scope: \"group\" | \"window-output\",\n): Record<string, unknown> {\n  const scopedCtx: GenerateCtx = { ...ctx, accumulatorContext: scope };\n  const out: Record<string, unknown> = {};\n  for (const entry of body.entries) {\n    if (entry.type !== \"KeyValueEntry\") {\n      throw new CodegenError(`Spread entries are not allowed in an accumulator-output object`, entry.pos);\n    }\n    if (entry.key.kind !== \"static\") {\n      throw new CodegenError(`Computed keys are not allowed in an accumulator-output object`, entry.pos);\n    }\n    out[entry.key.name] = generateWithCtx(entry.value, scopedCtx);\n  }\n  return out;\n}\n\n/**\n * Sub-pipeline entry point. Same as `generatePipeline` but starts from a\n * caller-supplied ctx. Used for literal sub-pipeline slots (`$facet.*`,\n * `$lookup.pipeline`, `$unionWith.pipeline`); `container` names which owning\n * stage so structural validation can enforce the forbidden-in-context bans\n * (e.g. `$out`/`$merge` inside any sub-pipeline) and the per-sub-pipeline\n * position rules.\n */\nfunction generatePipelineWithCtx(ast: Expr, startCtx: GenerateCtx, container: ContainerKind): unknown[] {\n  if (ast.type !== \"ArrayLiteral\") {\n    internalError(\"generatePipelineWithCtx expects an ArrayLiteral AST\");\n  }\n  // Nested lookups inside expression-body predicates are now materialised by\n  // `extractLookupCalls` with an `EnclosingLookupContext` thread-through (see\n  // lookup-translation.ts). Block-body and `$facet`/`$unionWith` sub-pipelines\n  // still walk through this path; those forms are caught at the per-statement\n  // level when `extractLookupCalls` runs over each stage body. (Block-body\n  // nested lookups themselves are still rejected upstream in\n  // `translatePredicate` \u2014 they need ctx threading through `lowerBlock`.)\n  for (const el of ast.elements) {\n    // `$$.push(...)` inside a sub-pipeline targets the *outer* collection but\n    // emits stages that would live inside the inner pipeline \u2014 the semantics are\n    // ambiguous and the MongoDB server has no equivalent shape. Reject.\n    if (el.type !== \"SpreadElement\") {\n      const innerPush =\n        el.type === \"AssignExpr\" || el.type === \"DeleteStmt\" || el.type === \"LetDecl\"\n          ? null\n          : detectUnionPush(el as Expr);\n      if (innerPush !== null) {\n        throw new CodegenError(\n          `'$$.push(...)' inside a sub-pipeline ('$lookup.pipeline', '$unionWith.pipeline', '$facet.*') is not supported \u2014 ` +\n            `$$.push emits '$unionWith' stages against the current (outer) collection. Hoist the push to a sibling stage in the outer pipeline.`,\n          innerPush.pos,\n        );\n      }\n    }\n  }\n  const out: unknown[] = [];\n  let updateBuffer: UpdateOp[] = [];\n  let ctx: GenerateCtx = startCtx;\n  let everHadLet = ctxHasLets(startCtx); // shouldn't happen for sub-pipelines, but safe\n  const validator = makePipelineValidator(container);\n\n  const flushUpdateOps = () => {\n    if (updateBuffer.length === 0) return;\n    for (const stage of generateUpdateOpGroups(updateBuffer, ctx)) out.push(stage);\n    updateBuffer = [];\n  };\n\n  ast.elements.forEach((el, i) => {\n    validator.checkBeforeElement(el.pos);\n    if (el.type === \"AssignExpr\" || el.type === \"DeleteStmt\") {\n      updateBuffer.push(el);\n      return;\n    }\n    if (el.type === \"LetDecl\") {\n      flushUpdateOps();\n      const stage = lowerLetDecl(el, ctx);\n      out.push(stage.set);\n      ctx = stage.ctx;\n      everHadLet = true;\n      return;\n    }\n    flushUpdateOps();\n    const shape = asStageShape(el);\n    if (shape !== null) validator.checkStage(shape.name, el.pos, i, shape.body);\n    const result = lowerStageElement(el, i, ctx);\n    out.push(result.stage);\n    ctx = result.ctx;\n  });\n  flushUpdateOps();\n  if (everHadLet && !shouldSkipTrailingNamespaceUnset(out)) out.push({ $unset: LET_NAMESPACE });\n  return out;\n}\n\n// \u2500\u2500 Error formatting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction formatNotAStageError(el: ArrayElement, index: number): string {\n  // Try to surface the offending name when we can guess one \u2014 gives users a\n  // precise pointer (\"Element 1: '$macth' is not a known stage. Did you mean\n  // '$match'?\") instead of the generic shape complaint.\n  if (el.type !== \"SpreadElement\") {\n    if (el.type === \"ObjectLiteral\") {\n      if (el.entries.length === 1) {\n        const entry = el.entries[0];\n        if (entry.type === \"KeyValueEntry\" && entry.key.kind === \"static\") {\n          const name = entry.key.name;\n          if (!lookupStage(name)) {\n            return formatUnknownStage(name, index);\n          }\n        }\n      } else if (el.entries.length > 1) {\n        return (\n          `Element ${index} of pipeline must be a single-key stage object ` +\n          `(e.g. \\`{ $match: ... }\\`), but found an object with ${el.entries.length} keys.`\n        );\n      }\n    }\n    if (el.type === \"OperatorCall\" && !lookupStage(el.name)) {\n      return formatUnknownStage(el.name, index);\n    }\n    // Bare predicate / expression in pipeline position is almost always a user\n    // who wants to filter \u2014 point them at `$match(...)` explicitly so they\n    // don't have to look it up. The semicolon-form pipeline (`$.age > 18;`)\n    // hits this path most often.\n    if (looksLikePredicate(el)) {\n      return (\n        `Element ${index} of pipeline is not a stage call. ` +\n        `To filter documents on a predicate, wrap it as \\`$match(...)\\` \u2014 ` +\n        `e.g. \\`$match($.age > 18)\\`. ` +\n        `Pipeline statements must be stage calls; available stages: ${formatStageList()}.`\n      );\n    }\n  }\n  return (\n    `Element ${index} of pipeline is not a recognised stage. ` +\n    `Expected \\`{ $stage: ... }\\` or \\`$stage(...)\\` where $stage is one of: ` +\n    `${formatStageList()}.`\n  );\n}\n\n/**\n * Heuristic: does this element look like a boolean predicate the user probably\n * meant to filter on? Comparison and logical binary ops, unary `!`, and the\n * `in` / `instanceof` shapes all qualify. Used only for friendlier error\n * messages \u2014 no behaviour change.\n */\nfunction looksLikePredicate(el: ArrayElement): boolean {\n  if (el.type === \"BinaryExpr\") {\n    const op = el.op;\n    return (\n      op === \"===\" ||\n      op === \"==\" ||\n      op === \"!==\" ||\n      op === \"!=\" ||\n      op === \"<\" ||\n      op === \"<=\" ||\n      op === \">\" ||\n      op === \">=\" ||\n      op === \"&&\" ||\n      op === \"||\"\n    );\n  }\n  if (el.type === \"UnaryExpr\" && el.op === \"!\") return true;\n  return false;\n}\n\nfunction formatUnknownStage(name: string, index: number): string {\n  const suffix = didYouMean(name, Object.keys(STAGES), (s) => s);\n  return `Element ${index} of pipeline: '${name}' is not a known aggregation stage.${suffix}`;\n}\n\nfunction formatStageList(): string {\n  // Compact list, alphabetised, capped to keep the error readable.\n  const all = Object.keys(STAGES).sort();\n  const head = all.slice(0, 12).join(\", \");\n  return `${head}, \u2026 (${all.length} total)`;\n}\n\n// \u2500\u2500 Lookup integration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Lower a Pipeline AST (a block-body lambda body, normalised by the parser) to a\n * stage array. Provided to lookup-translation as its SubPipelineLowerer so the\n * `$lookup.pipeline` body for a block-body lambda uses the same `;`-separated\n * semantics as a top-level pipeline. `extractLookupCalls` itself rejects nested\n * `$$$.<coll>.find/filter(...)` inside this block via `rejectNestedLookup`, so\n * by the time `lowerBlock` runs the block is free of nested lookups and can be\n * lowered with `generateImplicitPipeline` unchanged.\n */\nconst lowerBlock: SubPipelineLowerer = (block, ctx) => {\n  // `$$.push(...)` targets the *outer* collection but the stages it emits\n  // would live inside this lookup's `$lookup.pipeline` \u2014 semantically wrong\n  // (the push wouldn't union into the outer stream). Reject before lowering\n  // with a precise hoist-to-outer hint, mirroring the nested-lookup rule.\n  for (const stmt of block.stmts) {\n    const innerPush =\n      stmt.type === \"LetDecl\" ? null : stmt.type === \"UpdateFilter\" ? null : detectUnionPush(stmt as Expr);\n    if (innerPush !== null) {\n      throw new CodegenError(\n        `'$$.push(...)' inside a lookup's block-body lambda is not supported \u2014 $$.push appends documents to the outer collection's stream via '$unionWith', but the stages would land inside '$lookup.pipeline'. ` +\n          `Hoist the push to a sibling stage in the outer pipeline.`,\n        innerPush.pos,\n      );\n    }\n  }\n  return generateImplicitPipeline(block, ctx) as object[];\n};\n\n/**\n * Per-pipeline slot allocator plus a flag for whether any slot was handed out.\n * Used to decide whether to emit the trailing `$unset \"__jsmql\"` cleanup at\n * the end of a top-level pipeline \u2014 `__jsmql.__lookup<N>` slots ride the same\n * cleanup as `let`-bindings, so a pipeline with no lets but at least one\n * lookup still needs the trailing `$unset`.\n */\nfunction makeSlotTracking(): { alloc: SlotAllocator; used: () => boolean } {\n  const base = createSlotAllocator();\n  let touched = false;\n  return {\n    alloc: () => {\n      touched = true;\n      return base();\n    },\n    used: () => touched,\n  };\n}\n\n/**\n * Lower one `UpdateFilter` statement, splitting at any update op whose RHS is\n * a direct lookup. Adjacent non-lookup update ops keep coalescing through\n * `generateUpdateOpGroups`; a direct-lookup op flushes the buffer, emits the\n * lookup stages (using its LHS field path as the `$lookup.as` slot), and\n * resumes buffering on the next op. Chained-on-lookup and lookup-bearing\n * arithmetic RHSes go through `extractLookupCalls` first \u2014 the prologue\n * stages flush before the op is queued.\n */\n/**\n * The `$ =`-rooted / lookup `AssignExpr` sugar chain, shared by both pipeline\n * forms \u2014 `generatePipeline`'s `[\u2026]` elements and `lowerUpdateFilterWithLookups`'s\n * `,`-grouped ops. Tries each sugar in order and, on a hit, flushes the caller's\n * update buffer (via `flush`), pushes the lowered stages onto `out`, and returns\n * the (possibly let-cleared) ctx:\n *   - `$$ = \u2026`                              \u2192 replace-stream stages\n *   - `$ = { k: $$.filter(\u2026) }`             \u2192 `$facet`\n *   - `$ = <expr>`                          \u2192 `$replaceWith`\n *   - `$$$.<coll> = \u2026`                      \u2192 `$out` (signalled via `outPos`)\n *   - `$.<f> = $$$.<coll>.find/filter(\u2026)`   \u2192 `$lookup`\n * On a miss it returns `{ handled: false, bufferOp }` \u2014 the rewritten op (any\n * buried lookups already hoisted onto `out`) for the caller to push onto its\n * own update buffer.\n *\n * Per-form differences stay with the caller: first-stage detection (`isFirst`),\n * loop control (`return` vs `continue`), the buffer identity, and how an `$out`\n * terminal is recorded (`validator.markSugarOut` vs a `TerminalState`) \u2014 keyed\n * off the returned `outPos`.\n */\ntype AssignSugarResult =\n  | { handled: true; ctx: GenerateCtx; outPos: number | null }\n  | { handled: false; bufferOp: AssignExpr };\n\nfunction tryLowerAssignSugar(\n  op: AssignExpr,\n  ctx: GenerateCtx,\n  out: unknown[],\n  flush: () => void,\n  allocSlot: SlotAllocator,\n  lowerBlockFn: SubPipelineLowerer,\n  isFirst: boolean,\n): AssignSugarResult {\n  if (isReplaceStreamAssign(op)) {\n    flush();\n    const result = lowerReplaceStream(op, ctx, lowerBlockFn, allocSlot, isFirst);\n    for (const s of result.stages) out.push(s);\n    return { handled: true, ctx: result.clearLets ? clearCtxLets(ctx, \"$unionWith\") : ctx, outPos: null };\n  }\n  if (isReplaceRootAssign(op)) {\n    const facets = detectFacetShape(op.value);\n    if (facets !== null) {\n      flush();\n      for (const s of lowerFacet(facets, ctx, lowerBlockFn)) out.push(s);\n      return { handled: true, ctx: clearCtxLets(ctx, \"$facet\"), outPos: null };\n    }\n    flush();\n    for (const s of lowerReplaceRoot(op, ctx, allocSlot, lowerBlockFn)) out.push(s);\n    return { handled: true, ctx: clearCtxLets(ctx, \"$replaceWith\"), outPos: null };\n  }\n  const outTarget = detectOutAssign(op, ctx);\n  if (outTarget !== null) {\n    flush();\n    for (const s of lowerOut(op, outTarget, ctx, lowerBlockFn, allocSlot)) out.push(s);\n    return { handled: true, ctx, outPos: op.pos };\n  }\n  const direct = detectLookupCall(op.value, ctx);\n  if (direct !== null) {\n    validateLookupShape(op.value);\n    flush();\n    const asPath = updateOpWritePath(op);\n    for (const s of lowerLookup(direct, asPath, ctx, lowerBlockFn)) out.push(s);\n    return { handled: true, ctx, outPos: null };\n  }\n  const { stages, rewritten } = extractLookupCalls(op.value, ctx, allocSlot, lowerBlockFn);\n  if (stages.length > 0) {\n    flush();\n    for (const s of stages) out.push(s);\n  }\n  return { handled: false, bufferOp: { type: \"AssignExpr\", target: op.target, value: rewritten, pos: op.pos } };\n}\n\n/**\n * The statement-tail dispatch shared by both pipeline forms: a non-assignment\n * element that is either statement-only sugar or a stage call. Tries, in order:\n *   - `$$.push(\u2026)`                          \u2192 `$unionWith` stages\n *   - `$$.indexStats()` / `$$$$.currentOp()`/ \u2026 \u2192 a diagnostic source stage\n *     (first-stage-only)\n *   - otherwise a stage call/object         \u2192 lowered via `lowerStageElement`,\n *     with buried lookups hoisted to `out` first and stage-placement validated.\n * Pushes the resulting stage(s) onto `out` and returns the next ctx. The\n * `el.type !== \"SpreadElement\"` guard skips the sugar checks for a bare\n * `...spread` element (only reachable from the `[\u2026]` form) while still routing\n * it through stage lowering.\n */\nfunction lowerStatementTail(\n  el: ArrayElement,\n  i: number,\n  ctx: GenerateCtx,\n  out: unknown[],\n  validator: ReturnType<typeof makePipelineValidator>,\n  allocSlot: SlotAllocator,\n  lowerBlockFn: SubPipelineLowerer,\n): GenerateCtx {\n  if (el.type !== \"SpreadElement\") {\n    const pushCall = detectUnionPush(el as Expr);\n    if (pushCall !== null) {\n      for (const s of lowerUnionPush(pushCall, ctx, lowerBlockFn)) out.push(s);\n      return ctx;\n    }\n    if (el.type === \"MethodCall\" && isSystemStageCall(el)) {\n      const sys = resolveSystemStageCall(el);\n      if (out.length > 0) throw new CodegenError(notFirstStageMessage(sys), sys.callPos);\n      out.push(lowerSystemStageStmt(sys, ctx));\n      return ctx;\n    }\n    // Bare-statement stream chain: `$$.filter(p).map(f);` (no `$$ =` head),\n    // sugar for `$$ = $$.<chain>;`. Lowered against the live `out` so that a\n    // stage-coupled method composes with earlier statements \u2014 guaranteeing\n    // `$$.toSorted(c); $$.toReversed();` \u2261 `$$.toSorted(c).toReversed();`.\n    // `$$.push(...)` / `$$.indexStats()` are handled above; any other method on\n    // a bare `$$` (valid stream method, or an unknown one \u2192 actionable error\n    // from `applyStreamMethods`) flows through here. This supersedes the old\n    // `validateUnionPushShape` statement-position hook: every `$$.<method>(...)`\n    // is a CollectionRef-rooted chain, so it's caught here before reaching the\n    // generic stage path.\n    const streamChain = collectStreamChain(el as Expr);\n    if (streamChain.root.type === \"CollectionRef\" && streamChain.methods.length > 0) {\n      const clearLets = applyStreamMethods(\n        streamChain.methods,\n        out as object[],\n        ctx,\n        lowerBlockFn,\n        allocSlot,\n        el as Expr,\n      );\n      return clearLets ? clearCtxLets(ctx, \"$unionWith\") : ctx;\n    }\n  }\n  const rewrittenEl = extractFromStageElement(el, ctx, allocSlot, lowerBlockFn, out);\n  const shape = asStageShape(rewrittenEl);\n  if (shape !== null) validator.checkStage(shape.name, rewrittenEl.pos ?? el.pos, i, shape.body);\n  const result = lowerStageElement(rewrittenEl, i, ctx);\n  out.push(result.stage);\n  return result.ctx;\n}\n\nfunction lowerUpdateFilterWithLookups(\n  stmt: UpdateFilter,\n  startCtx: GenerateCtx,\n  allocSlot: SlotAllocator,\n  lowerBlockFn: SubPipelineLowerer,\n  globalStageIndex: number = 0,\n): { stages: object[]; ctx: GenerateCtx; terminal: TerminalState | null } {\n  const out: object[] = [];\n  let buffer: UpdateOp[] = [];\n  let ctx = startCtx;\n  let terminal: TerminalState | null = null;\n  const flush = () => {\n    if (buffer.length === 0) return;\n    for (const stage of generateUpdateOpGroups(buffer, ctx)) out.push(stage);\n    buffer = [];\n  };\n  for (const op of stmt.ops) {\n    if (terminal !== null) throw makeAfterTerminalError(terminal, op.pos);\n    if (op.type === \"AssignExpr\") {\n      const r = tryLowerAssignSugar(op, ctx, out, flush, allocSlot, lowerBlockFn, globalStageIndex + out.length === 0);\n      if (r.handled) {\n        ctx = r.ctx;\n        if (r.outPos !== null) terminal = { stageName: \"$out\", pos: r.outPos, viaSugar: true };\n        continue;\n      }\n      buffer.push(r.bufferOp);\n      continue;\n    }\n    // DeleteStmt \u2014 target is a field path; no lookups possible.\n    if (op.target.type === \"FieldRef\" && op.target.path === \"\") {\n      throw new CodegenError(\n        `Cannot 'delete $' \u2014 bare '$' is the whole document. Use '$ = <newDoc>' to replace it, or 'delete $.<field>' to drop a single field.`,\n        op.pos,\n      );\n    }\n    buffer.push(op);\n  }\n  flush();\n  return { stages: out, ctx, terminal };\n}\n\n/**\n * Extract lookups from one stage-call element (e.g. a `$project({...})` or\n * `{ $project: {...} }` whose body has a lookup buried in some entry). The\n * stage's body expressions are walked; lookups are materialised into internal\n * slots and prologue stages are pushed to `out` *before* the stage itself.\n * Returns the rewritten element (an ArrayElement of the same shape) so the\n * existing stage lowering machinery handles it unchanged.\n */\nfunction extractFromStageElement(\n  el: ArrayElement,\n  ctx: GenerateCtx,\n  allocSlot: SlotAllocator,\n  lowerBlockFn: SubPipelineLowerer,\n  out: unknown[],\n): ArrayElement {\n  if (el.type === \"OperatorCall\") {\n    const args = el.args.map((arg): CallArg => {\n      if (arg.type === \"SpreadElement\") {\n        const { stages, rewritten } = extractLookupCalls(arg.argument, ctx, allocSlot, lowerBlockFn);\n        for (const s of stages) out.push(s);\n        return { type: \"SpreadElement\", argument: rewritten, pos: arg.pos };\n      }\n      const { stages, rewritten } = extractLookupCalls(arg, ctx, allocSlot, lowerBlockFn);\n      for (const s of stages) out.push(s);\n      return rewritten;\n    });\n    return { type: \"OperatorCall\", name: el.name, style: el.style, args, pos: el.pos };\n  }\n  if (el.type === \"ObjectLiteral\") {\n    // Stage-object form: `{ $stage: <body> }`. Walk the entries.\n    const entries = el.entries.map((entry) => {\n      if (entry.type === \"SpreadElement\") {\n        const { stages, rewritten } = extractLookupCalls(entry.argument, ctx, allocSlot, lowerBlockFn);\n        for (const s of stages) out.push(s);\n        return { type: \"SpreadElement\" as const, argument: rewritten, pos: entry.pos };\n      }\n      const { stages, rewritten } = extractLookupCalls(entry.value, ctx, allocSlot, lowerBlockFn);\n      for (const s of stages) out.push(s);\n      return { type: \"KeyValueEntry\" as const, key: entry.key, value: rewritten, pos: entry.pos };\n    });\n    return { type: \"ObjectLiteral\", entries, pos: el.pos };\n  }\n  return el;\n}\n\n/**\n * Find the source position of the first `$$$.<coll>.find/filter(...)` chain\n * inside an ArrayElement, or null if none. Used by `generatePipelineWithCtx`\n * to surface a precise nested-lookup-not-supported error.\n */\nfunction findFirstLookupInElement(el: ArrayElement): number | null {\n  if (el.type === \"AssignExpr\") return findFirstLookupInExpr(el.value);\n  if (el.type === \"DeleteStmt\") return null;\n  if (el.type === \"LetDecl\") return findFirstLookupInExpr(el.value);\n  if (el.type === \"SpreadElement\") return findFirstLookupInExpr(el.argument);\n  return findFirstLookupInExpr(el as Expr);\n}\n\nfunction findFirstLookupInExpr(expr: Expr): number | null {\n  // findFirstLookupInExpr only locates a position for the nested-lookup\n  // rejection in `generatePipelineWithCtx`. The position is informational;\n  // the surrounding code has already established (structurally) that a\n  // lookup is present. EMPTY_CTX is safe here.\n  const direct = detectLookupCall(expr, EMPTY_CTX);\n  if (direct !== null) return direct.pos;\n  // Recurse into common shapes\n  if (expr.type === \"MethodCall\") {\n    const a = findFirstLookupInExpr(expr.object);\n    if (a !== null) return a;\n    for (const arg of expr.args) {\n      const a2 = arg.type === \"SpreadElement\" ? findFirstLookupInExpr(arg.argument) : findFirstLookupInExpr(arg);\n      if (a2 !== null) return a2;\n    }\n    return null;\n  }\n  if (expr.type === \"MemberAccess\") return findFirstLookupInExpr(expr.object);\n  if (expr.type === \"IndexAccess\") {\n    return findFirstLookupInExpr(expr.object) ?? findFirstLookupInExpr(expr.index);\n  }\n  if (expr.type === \"BinaryExpr\") return findFirstLookupInExpr(expr.left) ?? findFirstLookupInExpr(expr.right);\n  if (expr.type === \"UnaryExpr\") return findFirstLookupInExpr(expr.operand);\n  if (expr.type === \"TernaryExpr\") {\n    return (\n      findFirstLookupInExpr(expr.condition) ??\n      findFirstLookupInExpr(expr.consequent) ??\n      findFirstLookupInExpr(expr.alternate)\n    );\n  }\n  if (expr.type === \"OperatorCall\" || expr.type === \"MathCall\" || expr.type === \"ObjectCall\") {\n    for (const arg of expr.args) {\n      const a = arg.type === \"SpreadElement\" ? findFirstLookupInExpr(arg.argument) : findFirstLookupInExpr(arg);\n      if (a !== null) return a;\n    }\n    return null;\n  }\n  if (expr.type === \"ArrayLiteral\") {\n    for (const child of expr.elements) {\n      const a = findFirstLookupInElement(child);\n      if (a !== null) return a;\n    }\n    return null;\n  }\n  if (expr.type === \"ObjectLiteral\") {\n    for (const entry of expr.entries) {\n      if (entry.type === \"SpreadElement\") {\n        const a = findFirstLookupInExpr(entry.argument);\n        if (a !== null) return a;\n      } else {\n        if (entry.key.kind === \"computed\") {\n          const a = findFirstLookupInExpr(entry.key.expr);\n          if (a !== null) return a;\n        }\n        const a = findFirstLookupInExpr(entry.value);\n        if (a !== null) return a;\n      }\n    }\n    return null;\n  }\n  if (expr.type === \"Lambda\") {\n    if (expr.body !== undefined) return findFirstLookupInExpr(expr.body);\n    if (expr.block !== undefined) {\n      for (const stmt of expr.block.stmts) {\n        if (stmt.type === \"UpdateFilter\") {\n          for (const op of stmt.ops) {\n            if (op.type === \"AssignExpr\") {\n              const a = findFirstLookupInExpr(op.value);\n              if (a !== null) return a;\n            }\n          }\n        } else if (stmt.type === \"LetDecl\") {\n          const a = findFirstLookupInExpr(stmt.value);\n          if (a !== null) return a;\n        } else {\n          const a = findFirstLookupInExpr(stmt as Expr);\n          if (a !== null) return a;\n        }\n      }\n    }\n    return null;\n  }\n  return null;\n}\n"],
  "mappings": "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",
  "names": ["raw", "value", "MATH_METHODS", "MATH_CONSTANTS", "OBJECT_METHODS", "obj", "args", "value", "key", "obj", "def", "asFieldPath", "obj", "lowerBlock", "lookup", "lowerBlock", "acc", "project", "lowerBlock", "lowerBlock", "lowerBlock", "LET_NAMESPACE", "lookupStage", "stages", "rewritten"]
}
