import { Expression, type Expressions, type TypedExpression } from './expression.js'; import { ExpressionType } from './expression-type.js'; import { ParameterExpression } from './parameter-expression.js'; import type { ExpressionVisitor } from './visitors/expression-visitor.js'; /** * Represents a typed lambda expression. * @template T - The type of the lambda function. */ export class TypedLambdaExpression unknown> extends Expression { /** @override */ public get type(): ExpressionType.LambdaExpression { return ExpressionType.LambdaExpression; } /** All parameters defined for this lambda expression */ public readonly parameters: Parameters; /** * Initialize a new typed lambda expression instance * @param {Expressions} body - Expression representing the lambda's execution logic * @param {Parameters} parameters - List of parameter definitions for this lambda */ constructor(public readonly body: Expressions, ...parameters: Parameters) { super(); this.parameters = parameters; } /** * Accepts an expression visitor as part of the visitor pattern * @param visitor - Visitor instance implementing the lambda visitation logic */ public accept(visitor: ExpressionVisitor) { return visitor.visitLambda(this); } } /** * Infers parameter types from a function type and creates corresponding ParameterExpression instances. * @template T - The function type from which parameters are inferred. */ export type Parameters = T extends (a: infer T1) => unknown ? [ParameterExpression] : T extends (a: infer T1, b: infer T2) => unknown ? [ParameterExpression, ParameterExpression] : T extends (a: infer T1, b: infer T2, c: infer T3) => unknown ? [ParameterExpression, ParameterExpression, ParameterExpression] : T extends (a: infer T1, b: infer T2, c: infer T3, d: infer T4) => unknown ? [ParameterExpression, ParameterExpression, ParameterExpression, ParameterExpression] : T extends (a: infer T1, b: infer T2, c: infer T3, d: infer T4, e: infer T5) => unknown ? [ParameterExpression, ParameterExpression, ParameterExpression, ParameterExpression, ParameterExpression] : T extends (a: infer T1, b: infer T2, c: infer T3, d: infer T4, e: infer T5, f: infer T6) => unknown ? [ T1 extends never | void ? void : ParameterExpression, T2 extends never | void ? void : ParameterExpression, T3 extends never | void ? void : ParameterExpression, T4 extends never | void ? void : ParameterExpression, T5 extends never | void ? void : ParameterExpression, T6 extends never | void ? void : ParameterExpression ] : T extends (...args: unknown[]) => unknown ? ParameterExpression[] : never; /** * Represents a lambda expression. */ export class LambdaExpression extends TypedLambdaExpression<(...args: unknown[]) => unknown> { /** * Creates a strongly-typed lambda expression instance. * @template T - The function type representing the lambda's signature. * @template U - The return type of the lambda function. * @param {TypedExpression} body - The expression representing the lambda's body. * @param {Parameters} parameters - Array of parameter expressions matching the function's signature. * @returns {TypedLambdaExpression} A new typed lambda expression instance. */ static typed U, U>(body: TypedExpression, parameters: Parameters): TypedLambdaExpression { return new TypedLambdaExpression(body, ...parameters); } /** * Creates a new LambdaExpression instance. * @param {Expressions} body - The expression tree representing the lambda's execution logic. * @param {...Parameters<(...args: unknown[]) => unknown>} parameters - List of parameter expressions defining the lambda's input. */ constructor(public readonly body: Expressions, ...parameters: Parameters<(...args: unknown[]) => unknown>) { super(body, ...parameters); } }