UNPKG

mlld

Version:

mlld: a modular prompt scripting language

174 lines (172 loc) 6.47 kB
import { logger } from './chunk-XGMRAGIT.mjs'; import { isExecutable } from './chunk-V5L6FBQT.mjs'; import { __name } from './chunk-OMKLS24H.mjs'; // interpreter/eval/foreach.ts async function evaluateForeachCommand(foreachExpr, env) { if (process.env.MLLD_DEBUG === "true") { logger.debug("evaluateForeachCommand called with:", { foreachExpr }); } const { execInvocation, arrays } = foreachExpr; let commandName; let commandArgs = []; if (execInvocation.type === "ExecInvocation") { commandName = execInvocation.commandRef.name; commandArgs = execInvocation.commandRef.args || []; } else if (execInvocation.identifier) { commandName = execInvocation.identifier; } else { throw new Error("Invalid foreach command structure"); } const cmdVariable = env.getVariable(commandName); if (!cmdVariable) { throw new Error(`Command not found: ${commandName}`); } if (!isExecutable(cmdVariable)) { throw new Error(`Variable '${commandName}' cannot be used with foreach. Expected an @exec command or @text template with parameters, but got type: ${cmdVariable.type}`); } const { evaluateDataValue } = await import('./data-value-evaluator-UFIUOP64.mjs'); const evaluatedArrays = []; const arrayNodes = arrays || commandArgs; for (let i = 0; i < arrayNodes.length; i++) { const arrayVar = arrayNodes[i]; const arrayValue = await evaluateDataValue(arrayVar, env); if (!Array.isArray(arrayValue)) { throw new Error(`Argument ${i + 1} to foreach must be an array, got ${typeof arrayValue}`); } evaluatedArrays.push(arrayValue); } validateArrayInputs(evaluatedArrays); if (!isWithinPerformanceLimit(evaluatedArrays)) { const totalCombinations = evaluatedArrays.reduce((total, arr) => total * arr.length, 1); throw new Error(`Foreach operation would generate ${totalCombinations} combinations, which exceeds the performance limit. Consider reducing array sizes or using more specific filtering.`); } const definition = cmdVariable.value; const paramCount = cmdVariable.paramNames?.length || definition.paramNames?.length || 0; if (evaluatedArrays.length !== paramCount) { const paramType = definition.sourceDirective === "text" ? "Text template" : "Command"; throw new Error(`${paramType} '${commandName}' expects ${paramCount} parameter${paramCount !== 1 ? "s" : ""}, but foreach is passing ${evaluatedArrays.length} array${evaluatedArrays.length !== 1 ? "s" : ""}`); } const tuples = cartesianProduct(evaluatedArrays); const { evaluateExecInvocation } = await import('./exec-invocation-BKHC2VUW.mjs'); const results = []; for (let i = 0; i < tuples.length; i++) { const tuple = tuples[i]; try { const execInvocationNode = { type: "ExecInvocation", commandRef: { identifier: commandName, args: tuple // Use tuple values directly as arguments }, withClause: null }; const result = await evaluateExecInvocation(execInvocationNode, env); results.push(result.value); } catch (error) { const params = cmdVariable.paramNames || definition.paramNames || []; const iterationContext = params.map((param, index) => `${param}: ${JSON.stringify(tuple[index])}`).join(", "); throw new Error(`Error in foreach iteration ${i + 1} (${iterationContext}): ${error instanceof Error ? error.message : String(error)}`); } } return results; } __name(evaluateForeachCommand, "evaluateForeachCommand"); async function evaluateForeachSection(foreachExpr, env) { return evaluateForeachCommand(foreachExpr, env); } __name(evaluateForeachSection, "evaluateForeachSection"); async function validateForeachExpression(foreachExpr, env) { const errors = []; try { if (!foreachExpr || typeof foreachExpr !== "object") { errors.push("Foreach expression must be an object"); return { valid: false, errors }; } const { execInvocation } = foreachExpr.value || foreachExpr; if (!execInvocation) { errors.push("Foreach expression missing exec invocation"); return { valid: false, errors }; } let commandName; if (execInvocation.type === "ExecInvocation") { commandName = execInvocation.commandRef.name; } else if (execInvocation.identifier) { commandName = execInvocation.identifier; } else { errors.push("Invalid foreach command structure"); return { valid: false, errors }; } const cmdVariable = env.getVariable(commandName); if (!cmdVariable) { errors.push(`Command not found: ${commandName}`); } else if (!isExecutable(cmdVariable)) { errors.push(`Variable '${commandName}' is not executable`); } return { valid: errors.length === 0, errors }; } catch (error) { errors.push(`Validation error: ${error instanceof Error ? error.message : String(error)}`); return { valid: false, errors }; } } __name(validateForeachExpression, "validateForeachExpression"); function validateArrayInputs(arrays) { if (arrays.length === 0) { throw new Error("Foreach requires at least one array argument"); } for (let i = 0; i < arrays.length; i++) { const arr = arrays[i]; if (!Array.isArray(arr)) { throw new Error(`Argument ${i + 1} must be an array`); } if (arr.length === 0) { throw new Error(`Array ${i + 1} cannot be empty`); } } } __name(validateArrayInputs, "validateArrayInputs"); function isWithinPerformanceLimit(arrays) { const MAX_COMBINATIONS = 1e4; const totalCombinations = arrays.reduce((total, arr) => total * arr.length, 1); return totalCombinations <= MAX_COMBINATIONS; } __name(isWithinPerformanceLimit, "isWithinPerformanceLimit"); function cartesianProduct(arrays) { if (arrays.length === 0) return []; if (arrays.length === 1) return arrays[0].map((item) => [ item ]); const result = []; const [head, ...tail] = arrays; const tailProduct = cartesianProduct(tail); for (const headItem of head) { for (const tailItem of tailProduct) { result.push([ headItem, ...tailItem ]); } } return result; } __name(cartesianProduct, "cartesianProduct"); export { evaluateForeachCommand, evaluateForeachSection, validateForeachExpression }; //# sourceMappingURL=chunk-ODBVL5OR.mjs.map //# sourceMappingURL=chunk-ODBVL5OR.mjs.map