mlld
Version:
mlld: a modular prompt scripting language
311 lines (309 loc) • 9.37 kB
JavaScript
import { evaluate } from './chunk-FYMHT7UG.mjs';
import { isTextLike, isArray, isObject, isCommandResult, isPipelineInput } from './chunk-V5L6FBQT.mjs';
import { __name } from './chunk-OMKLS24H.mjs';
// interpreter/eval/expression.ts
function isTruthy(value) {
if (value && typeof value === "object" && "type" in value && "name" in value) {
const variable = value;
if (isTextLike(variable)) {
const str = variable.value;
if (str === "" || str.toLowerCase() === "false" || str === "0") {
return false;
}
return true;
} else if (isArray(variable)) {
return variable.value.length > 0;
} else if (isObject(variable)) {
return Object.keys(variable.value).length > 0;
} else if (isCommandResult(variable)) {
return variable.value.trim().length > 0;
} else if (isPipelineInput(variable)) {
return variable.value.text.length > 0;
}
return isTruthy(variable.value);
}
if (value === null || value === void 0) {
return false;
}
if (typeof value === "boolean") {
return value;
}
if (typeof value === "number") {
return value !== 0 && !isNaN(value);
}
if (typeof value === "string") {
if (value === "*") {
return true;
}
if (value === "") {
return false;
}
if (value.toLowerCase() === "false") {
return false;
}
if (value === "0") {
return false;
}
return true;
}
if (Array.isArray(value)) {
return value.length > 0;
}
if (typeof value === "object") {
return Object.keys(value).length > 0;
}
return !!value;
}
__name(isTruthy, "isTruthy");
async function evaluateExpression(node, env, context) {
if (process.env.MLLD_DEBUG === "true") {
console.log("[DEBUG] evaluateExpression called with node type:", node.type);
if (node.type === "BinaryExpression") {
console.log("[DEBUG] Binary operator:", node.operator);
}
}
if (node.type === "BinaryExpression") {
return evaluateBinaryExpression(node, env, context);
} else if (node.type === "TernaryExpression") {
return evaluateTernaryExpression(node, env, context);
} else if (node.type === "UnaryExpression") {
return evaluateUnaryExpression(node, env, context);
}
throw new Error(`Unknown expression type: ${node.type}`);
}
__name(evaluateExpression, "evaluateExpression");
async function evaluateBinaryExpression(node, env, context) {
let { operator, left, right } = node;
if (Array.isArray(operator)) {
operator = operator[0];
}
if (process.env.MLLD_DEBUG === "true") {
console.log("[DEBUG] evaluateBinaryExpression called with operator:", operator);
console.log("[DEBUG] evaluateBinaryExpression:", {
operator,
leftType: left.type,
rightType: right.type,
left: left.type === "VariableReference" ? left.identifier : left,
right: right.type === "VariableReference" ? right.identifier : right
});
}
const expressionContext = {
isExpression: true,
...context
};
if (operator === "&&") {
const leftResult2 = await evaluate(left, env, expressionContext);
const leftTruthy = isTruthy(leftResult2.value);
if (!leftTruthy) {
return {
value: leftResult2.value,
env
};
}
const rightResult2 = await evaluate(right, env, expressionContext);
return {
value: rightResult2.value,
env
};
}
if (operator === "||") {
const leftResult2 = await evaluate(left, env, expressionContext);
const leftTruthy = isTruthy(leftResult2.value);
if (process.env.MLLD_DEBUG === "true") {
console.log("[DEBUG] || operator left side:", {
left: leftResult2.value,
leftTruthy,
leftType: typeof leftResult2.value,
isVariable: leftResult2.value && typeof leftResult2.value === "object" && "type" in leftResult2.value
});
}
if (leftTruthy) {
return {
value: leftResult2.value,
env
};
}
const rightResult2 = await evaluate(right, env, expressionContext);
if (process.env.MLLD_DEBUG === "true") {
console.log("[DEBUG] || operator right side:", {
right: rightResult2.value,
rightTruthy: isTruthy(rightResult2.value)
});
}
return {
value: rightResult2.value,
env
};
}
const leftResult = await evaluate(left, env, expressionContext);
const rightResult = await evaluate(right, env, expressionContext);
if (process.env.MLLD_DEBUG === "true") {
console.log("[DEBUG] Evaluated operands:", {
leftResult: leftResult.value,
rightResult: rightResult.value,
leftIsVariable: leftResult.value && typeof leftResult.value === "object" && "type" in leftResult.value,
rightIsVariable: rightResult.value && typeof rightResult.value === "object" && "type" in rightResult.value
});
}
if (operator === "==") {
const equal = isEqual(leftResult.value, rightResult.value);
if (process.env.MLLD_DEBUG === "true") {
console.log("[DEBUG] == comparison:", {
left: leftResult.value,
leftType: typeof leftResult.value,
right: rightResult.value,
rightType: typeof rightResult.value,
equal
});
}
return {
value: equal,
env
};
}
if (operator === "!=") {
const equal = isEqual(leftResult.value, rightResult.value);
return {
value: !equal,
env
};
}
if (operator === "<") {
const leftNum = toNumber(leftResult.value);
const rightNum = toNumber(rightResult.value);
console.log("[DEBUG] < comparison:", leftResult.value, "<", rightResult.value, "=", leftNum < rightNum);
return {
value: leftNum < rightNum,
env
};
}
if (operator === ">") {
const leftNum = toNumber(leftResult.value);
const rightNum = toNumber(rightResult.value);
return {
value: leftNum > rightNum,
env
};
}
if (operator === "<=") {
const leftNum = toNumber(leftResult.value);
const rightNum = toNumber(rightResult.value);
return {
value: leftNum <= rightNum,
env
};
}
if (operator === ">=") {
const leftNum = toNumber(leftResult.value);
const rightNum = toNumber(rightResult.value);
return {
value: leftNum >= rightNum,
env
};
}
throw new Error(`Unknown binary operator: ${operator}`);
}
__name(evaluateBinaryExpression, "evaluateBinaryExpression");
async function evaluateTernaryExpression(node, env, context) {
const { condition, trueBranch, falseBranch } = node;
const condResult = await evaluate(condition, env, {
isExpression: true,
...context
});
const condTruthy = isTruthy(condResult.value);
if (condTruthy) {
return evaluate(trueBranch, env, {
isExpression: true,
...context
});
} else {
return evaluate(falseBranch, env, {
isExpression: true,
...context
});
}
}
__name(evaluateTernaryExpression, "evaluateTernaryExpression");
async function evaluateUnaryExpression(node, env, context) {
const { operator, operand } = node;
if (operator === "!") {
const operandResult = await evaluate(operand, env, {
isExpression: true,
...context
});
const operandTruthy = isTruthy(operandResult.value);
return {
value: !operandTruthy,
env
};
}
throw new Error(`Unknown unary operator: ${operator}`);
}
__name(evaluateUnaryExpression, "evaluateUnaryExpression");
function isEqual(a, b) {
const aValue = extractValue(a);
const bValue = extractValue(b);
if (aValue === null || aValue === void 0) {
return bValue === null || bValue === void 0;
}
if (bValue === null || bValue === void 0) {
return false;
}
if (typeof aValue === "string" && typeof bValue === "boolean") {
return aValue === "true" && bValue === true || aValue === "false" && bValue === false;
}
if (typeof bValue === "string" && typeof aValue === "boolean") {
return bValue === "true" && aValue === true || bValue === "false" && aValue === false;
}
if (typeof aValue === "string" && typeof bValue === "number") {
const numA = Number(aValue);
return !isNaN(numA) && numA === bValue;
}
if (typeof bValue === "string" && typeof aValue === "number") {
const numB = Number(bValue);
return !isNaN(numB) && numB === aValue;
}
return aValue === bValue;
}
__name(isEqual, "isEqual");
function extractValue(value) {
if (value && typeof value === "object" && "type" in value && "value" in value) {
const variable = value;
return variable.value;
}
return value;
}
__name(extractValue, "extractValue");
function toNumber(value) {
if (value && typeof value === "object" && "type" in value && "value" in value) {
const variable = value;
return toNumber(variable.value);
}
if (value === null) {
return 0;
}
if (value === void 0) {
return NaN;
}
if (typeof value === "boolean") {
return value ? 1 : 0;
}
if (typeof value === "number") {
return value;
}
if (typeof value === "string") {
if (value === "true") {
return 1;
}
if (value === "false") {
return 0;
}
const num = Number(value);
return num;
}
return NaN;
}
__name(toNumber, "toNumber");
export { evaluateExpression, isEqual, isTruthy, toNumber };
//# sourceMappingURL=expression-CKCH5HUL.mjs.map
//# sourceMappingURL=expression-CKCH5HUL.mjs.map