import * as ts from 'typescript';
import { MacroContext } from '@typesugar/core';

/**
 * Comprehension Utilities
 *
 * Shared types and helper functions for the `let:/yield:` and `par:/yield:`
 * labeled block macros.
 */

/**
 * A monadic bind step: `name << expr` or `name << expr || fallback`
 *
 * Binds the result of a monadic expression to a name. For intermediate steps,
 * generates `.flatMap(name => ...)`. For the final step, generates `.map(name => ...)`.
 *
 * If `orElse` is present, wraps the expression with `.orElse(() => fallback)`.
 */
interface BindStep {
    kind: "bind";
    /** The variable name to bind (or "_" for discarded results) */
    name: string;
    /** The monadic expression to bind */
    effect: ts.Expression;
    /** Optional fallback expression (from `<< expr || alt` or `<< expr ?? alt`) */
    orElse?: ts.Expression;
    /** Original AST node for error reporting */
    node: ts.Node;
}
/**
 * A pure map step: `name = expr`
 *
 * Computes a pure value from previous bindings without unwrapping a monadic type.
 * Generated as an IIFE: `((name) => continuation)(expr)`
 */
interface MapStep {
    kind: "map";
    /** The variable name to bind */
    name: string;
    /** The pure expression to compute */
    expression: ts.Expression;
    /** Original AST node for error reporting */
    node: ts.Node;
}
/**
 * A guard/filter step: `if (cond) {}`
 *
 * Short-circuits the comprehension if the condition is false.
 * Generated as a ternary: `cond ? continuation : undefined`
 *
 * Note: Guards are only supported in monadic `let:` blocks, not applicative `par:` blocks.
 */
interface GuardStep {
    kind: "guard";
    /** The condition to check */
    condition: ts.Expression;
    /** Original AST node for error reporting */
    node: ts.Node;
}
/**
 * A step in a comprehension (let: or par: block).
 */
type ComprehensionStep = BindStep | MapStep | GuardStep;
/**
 * Extract the yield/return expression from a continuation block.
 *
 * Handles:
 * - Block with single expression statement: `yield: { expr }`
 * - Block with return statement: `yield: { return expr; }`
 * - Expression statement: `yield: expr`
 *
 * Detects common mistakes:
 * - Comma expressions that should be object literals: `yield: { a, b }`
 * - Nested blocks: `yield: { { a, b } }`
 */
declare function extractReturnExpr(ctx: MacroContext, stmt: ts.Statement): ts.Expression | undefined;
/**
 * Infer the type constructor name from an expression's type.
 *
 * Used to determine which FlatMap instance to use and whether to emit
 * `.then()` for Promises, `Effect.flatMap()` for Effect, etc.
 *
 * @returns The type constructor name (e.g., "Array", "Promise", "Option", "Effect")
 */
declare function inferTypeConstructor(expr: ts.Expression, typeChecker: ts.TypeChecker): string | undefined;
/**
 * Collect all identifiers referenced in an expression (deep scan).
 * Used to validate that par: bindings are independent.
 */
declare function collectReferencedIdentifiers(expr: ts.Expression): Set<string>;
/**
 * Create an arrow function: `(param) => body`
 */
declare function createArrowFn(factory: ts.NodeFactory, paramName: string, body: ts.Expression): ts.ArrowFunction;
/**
 * Create a method call: `expr.method(arg)`
 */
declare function createMethodCall(factory: ts.NodeFactory, expr: ts.Expression, method: string, arg: ts.Expression): ts.CallExpression;
/**
 * Create an IIFE: `((param) => body)(arg)`
 *
 * Used for pure map steps to inline computations.
 */
declare function createIIFE(factory: ts.NodeFactory, paramName: string, body: ts.Expression, arg: ts.Expression): ts.CallExpression;

export { type BindStep as B, type ComprehensionStep as C, type GuardStep as G, type MapStep as M, createArrowFn as a, createIIFE as b, collectReferencedIdentifiers as c, createMethodCall as d, extractReturnExpr as e, inferTypeConstructor as i };
