UNPKG

mlld

Version:

mlld: a modular prompt scripting language

1 lines 15.5 kB
{"version":3,"sources":["../interpreter/eval/foreach.ts"],"names":["evaluateForeachCommand","foreachExpr","env","process","MLLD_DEBUG","logger","debug","execInvocation","arrays","commandName","commandArgs","type","commandRef","name","args","identifier","Error","cmdVariable","getVariable","isExecutable","evaluateDataValue","evaluatedArrays","arrayNodes","i","length","arrayVar","arrayValue","Array","isArray","push","validateArrayInputs","isWithinPerformanceLimit","totalCombinations","reduce","total","arr","definition","value","paramCount","paramNames","paramType","sourceDirective","tuples","cartesianProduct","evaluateExecInvocation","results","tuple","execInvocationNode","withClause","result","error","params","iterationContext","map","param","index","JSON","stringify","join","message","String","evaluateForeachSection","validateForeachExpression","errors","valid","MAX_COMBINATIONS","item","head","tail","tailProduct","headItem","tailItem"],"mappings":"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","file":"chunk-ODBVL5OR.mjs","sourcesContent":["import type { Environment } from '../env/Environment';\nimport { isExecutable } from '@core/types/variable';\nimport { logger } from '@core/utils/logger';\n\n/**\n * Evaluate a foreach command expression by applying an executable to arrays of values.\n * Uses the standard evaluateExecInvocation() for consistent parameter handling.\n * \n * @param foreachExpr - The foreach command expression to evaluate\n * @param env - The evaluation environment\n * @returns Array of results from command execution\n */\nexport async function evaluateForeachCommand(\n foreachExpr: any,\n env: Environment\n): Promise<any[]> {\n // Debug logging\n if (process.env.MLLD_DEBUG === 'true') {\n logger.debug('evaluateForeachCommand called with:', { foreachExpr });\n }\n \n const { execInvocation, arrays } = foreachExpr;\n \n // Extract command name and arguments from execInvocation\n let commandName: string;\n let commandArgs: any[] = [];\n \n if (execInvocation.type === 'ExecInvocation') {\n // Handle @func(args) exec invocation\n commandName = execInvocation.commandRef.name;\n commandArgs = execInvocation.commandRef.args || [];\n } else if (execInvocation.identifier) {\n // Handle @var variable reference (legacy support)\n commandName = execInvocation.identifier;\n } else {\n throw new Error('Invalid foreach command structure');\n }\n \n // 1. Resolve the command variable\n const cmdVariable = env.getVariable(commandName);\n if (!cmdVariable) {\n throw new Error(`Command not found: ${commandName}`);\n }\n \n if (!isExecutable(cmdVariable)) {\n throw new Error(`Variable '${commandName}' cannot be used with foreach. Expected an @exec command or @text template with parameters, but got type: ${cmdVariable.type}`);\n }\n \n // 2. Evaluate all array arguments (use arrays property from AST)\n const { evaluateDataValue } = await import('./data-value-evaluator');\n const evaluatedArrays: any[][] = [];\n \n // Use the arrays property from the foreach AST node\n const arrayNodes = arrays || commandArgs;\n \n for (let i = 0; i < arrayNodes.length; i++) {\n const arrayVar = arrayNodes[i];\n const arrayValue = await evaluateDataValue(arrayVar, env);\n \n if (!Array.isArray(arrayValue)) {\n throw new Error(`Argument ${i + 1} to foreach must be an array, got ${typeof arrayValue}`);\n }\n \n evaluatedArrays.push(arrayValue);\n }\n \n // 3. Validate array inputs and performance limits\n validateArrayInputs(evaluatedArrays);\n \n if (!isWithinPerformanceLimit(evaluatedArrays)) {\n const totalCombinations = evaluatedArrays.reduce((total, arr) => total * arr.length, 1);\n throw new Error(`Foreach operation would generate ${totalCombinations} combinations, which exceeds the performance limit. Consider reducing array sizes or using more specific filtering.`);\n }\n \n // 4. Check parameter count matches array count\n const definition = cmdVariable.value;\n const paramCount = cmdVariable.paramNames?.length || definition.paramNames?.length || 0;\n if (evaluatedArrays.length !== paramCount) {\n const paramType = definition.sourceDirective === 'text' ? 'Text template' : 'Command';\n throw new Error(`${paramType} '${commandName}' expects ${paramCount} parameter${paramCount !== 1 ? 's' : ''}, but foreach is passing ${evaluatedArrays.length} array${evaluatedArrays.length !== 1 ? 's' : ''}`);\n }\n \n // 5. Generate cartesian product\n const tuples = cartesianProduct(evaluatedArrays);\n \n // 6. Execute command for each tuple using standard exec invocation\n const { evaluateExecInvocation } = await import('./exec-invocation');\n const results: any[] = [];\n \n for (let i = 0; i < tuples.length; i++) {\n const tuple = tuples[i];\n \n try {\n // Create an ExecInvocation node with the current tuple values as arguments\n const execInvocationNode = {\n type: 'ExecInvocation',\n commandRef: {\n identifier: commandName,\n args: tuple // Use tuple values directly as arguments\n },\n withClause: null\n };\n \n // Use the standard exec invocation evaluator\n const result = await evaluateExecInvocation(execInvocationNode as any, env);\n results.push(result.value);\n } catch (error) {\n // Include iteration context in error message\n const params = cmdVariable.paramNames || definition.paramNames || [];\n const iterationContext = params.map((param: string, index: number) => \n `${param}: ${JSON.stringify(tuple[index])}`\n ).join(', ');\n \n throw new Error(\n `Error in foreach iteration ${i + 1} (${iterationContext}): ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n \n return results;\n}\n\n/**\n * Evaluate a foreach section expression.\n */\nexport async function evaluateForeachSection(\n foreachExpr: any,\n env: Environment\n): Promise<any[]> {\n // Implementation for section-based foreach\n // This would handle cases like: foreach \"section\" from [path](@array)\n // For now, delegate to command-based foreach\n return evaluateForeachCommand(foreachExpr, env);\n}\n\n/**\n * Validate foreach expression structure and arguments.\n */\nexport async function validateForeachExpression(\n foreachExpr: any,\n env: Environment\n): Promise<{ valid: boolean; errors: string[] }> {\n const errors: string[] = [];\n \n try {\n // Basic structure validation\n if (!foreachExpr || typeof foreachExpr !== 'object') {\n errors.push('Foreach expression must be an object');\n return { valid: false, errors };\n }\n \n const { execInvocation } = foreachExpr.value || foreachExpr;\n if (!execInvocation) {\n errors.push('Foreach expression missing exec invocation');\n return { valid: false, errors };\n }\n \n // Command validation\n let commandName: string;\n if (execInvocation.type === 'ExecInvocation') {\n commandName = execInvocation.commandRef.name;\n } else if (execInvocation.identifier) {\n commandName = execInvocation.identifier;\n } else {\n errors.push('Invalid foreach command structure');\n return { valid: false, errors };\n }\n \n const cmdVariable = env.getVariable(commandName);\n if (!cmdVariable) {\n errors.push(`Command not found: ${commandName}`);\n } else if (!isExecutable(cmdVariable)) {\n errors.push(`Variable '${commandName}' is not executable`);\n }\n \n return { valid: errors.length === 0, errors };\n } catch (error) {\n errors.push(`Validation error: ${error instanceof Error ? error.message : String(error)}`);\n return { valid: false, errors };\n }\n}\n\n// Helper functions\n\nfunction validateArrayInputs(arrays: any[][]): void {\n if (arrays.length === 0) {\n throw new Error('Foreach requires at least one array argument');\n }\n \n for (let i = 0; i < arrays.length; i++) {\n const arr = arrays[i];\n if (!Array.isArray(arr)) {\n throw new Error(`Argument ${i + 1} must be an array`);\n }\n if (arr.length === 0) {\n throw new Error(`Array ${i + 1} cannot be empty`);\n }\n }\n}\n\nfunction isWithinPerformanceLimit(arrays: any[][]): boolean {\n const MAX_COMBINATIONS = 10000; // Configurable limit\n const totalCombinations = arrays.reduce((total, arr) => total * arr.length, 1);\n return totalCombinations <= MAX_COMBINATIONS;\n}\n\nfunction cartesianProduct(arrays: any[][]): any[][] {\n if (arrays.length === 0) return [];\n if (arrays.length === 1) return arrays[0].map(item => [item]);\n \n const result: any[][] = [];\n const [head, ...tail] = arrays;\n const tailProduct = cartesianProduct(tail);\n \n for (const headItem of head) {\n for (const tailItem of tailProduct) {\n result.push([headItem, ...tailItem]);\n }\n }\n \n return result;\n}"]}