// src/macros/comprehension-utils.ts
import * as ts from "typescript";
function isCommaExpression(expr) {
  return ts.isBinaryExpression(expr) && expr.operatorToken.kind === ts.SyntaxKind.CommaToken;
}
function looksLikeIntendedObjectLiteral(expr) {
  if (!isCommaExpression(expr))
    return false;
  const parts = [];
  let current = expr;
  while (ts.isBinaryExpression(current) && current.operatorToken.kind === ts.SyntaxKind.CommaToken) {
    parts.push(current.right);
    current = current.left;
  }
  parts.push(current);
  return parts.every((p) => ts.isIdentifier(p));
}
function extractReturnExpr(ctx, stmt) {
  if (ts.isBlock(stmt)) {
    const lastStmt = stmt.statements[stmt.statements.length - 1];
    if (stmt.statements.length > 1) {
      ctx.reportWarning(stmt, "yield: block has multiple statements; only the last expression is used. Preceding statements will be discarded.");
    }
    if (lastStmt && ts.isExpressionStatement(lastStmt)) {
      const expr = lastStmt.expression;
      if (looksLikeIntendedObjectLiteral(expr)) {
        ctx.reportError(lastStmt, "yield: block contains a comma expression, not an object literal. Did you mean `yield: ({ user, posts })`? Use parentheses to create an object literal.");
        return expr;
      }
      return expr;
    }
    if (lastStmt && ts.isReturnStatement(lastStmt) && lastStmt.expression) {
      return lastStmt.expression;
    }
    if (lastStmt && ts.isBlock(lastStmt)) {
      ctx.reportError(lastStmt, "yield: contains a nested block, not an object literal. To return an object, use `yield: ({ user, posts })` with parentheses.");
      return void 0;
    }
    if (stmt.statements.length === 0) {
      ctx.reportError(stmt, "yield: block is empty. It must contain an expression.");
      return void 0;
    }
    ctx.reportError(stmt, "yield: block should contain a single expression or object literal");
    return void 0;
  }
  if (ts.isExpressionStatement(stmt)) {
    return stmt.expression;
  }
  return void 0;
}
function inferTypeConstructor(expr, typeChecker) {
  const type = typeChecker.getTypeAtLocation(expr);
  const typeString = typeChecker.typeToString(type);
  if (type.symbol?.name === "Array" || /^[A-Za-z_]\w*\[\]$/.test(typeString)) {
    return "Array";
  }
  if (type.symbol?.name === "Promise" || typeString.startsWith("Promise<")) {
    return "Promise";
  }
  if (type.symbol?.name === "Effect" || typeString.startsWith("Effect<") || typeString.includes("Effect.Effect<")) {
    return "Effect";
  }
  if (type.symbol?.name === "Iterable" || typeString.startsWith("Iterable<")) {
    return "Iterable";
  }
  if (type.symbol?.name === "AsyncIterable" || typeString.startsWith("AsyncIterable<")) {
    return "AsyncIterable";
  }
  if (type.symbol?.name) {
    return type.symbol.name;
  }
  const match = typeString.match(/^(\w+)</);
  if (match) {
    return match[1];
  }
  return void 0;
}
function collectReferencedIdentifiers(expr) {
  const refs = /* @__PURE__ */ new Set();
  function walk(node) {
    if (ts.isIdentifier(node)) {
      refs.add(node.text);
    }
    ts.forEachChild(node, walk);
  }
  walk(expr);
  return refs;
}
function createArrowFn(factory, paramName, body) {
  return factory.createArrowFunction(void 0, void 0, [factory.createParameterDeclaration(void 0, void 0, factory.createIdentifier(paramName))], void 0, factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), body);
}
function createMethodCall(factory, expr, method, arg) {
  return factory.createCallExpression(factory.createPropertyAccessExpression(expr, factory.createIdentifier(method)), void 0, [arg]);
}
function createIIFE(factory, paramName, body, arg) {
  return factory.createCallExpression(factory.createParenthesizedExpression(createArrowFn(factory, paramName, body)), void 0, [arg]);
}

export {
  extractReturnExpr,
  inferTypeConstructor,
  collectReferencedIdentifiers,
  createArrowFn,
  createMethodCall,
  createIIFE
};
//# sourceMappingURL=chunk-RZHX2YRY.js.map