mlld
Version:
mlld: llm scripting language
185 lines (183 loc) • 6.52 kB
JavaScript
import { isTruthy, toNumber, isEqual } from './chunk-6FAJL6ND.mjs';
import { evaluate } from './chunk-6SG7EQJL.mjs';
import { MlldDirectiveError } from './chunk-YVSXROKS.mjs';
import { __name } from './chunk-NJQWMXLH.mjs';
// interpreter/eval/expressions.ts
async function evaluateUnifiedExpression(node, env) {
try {
switch (node.type) {
case "BinaryExpression":
return await evaluateBinaryExpression(node, env);
case "UnaryExpression":
return await evaluateUnaryExpression(node, env);
case "TernaryExpression":
return await evaluateTernaryExpression(node, env);
case "ArrayFilterExpression":
return await evaluateArrayFilterExpression(node, env);
case "ArraySliceExpression":
return await evaluateArraySliceExpression(node, env);
case "Literal":
if (node.valueType === "none") {
throw new Error('The "none" keyword can only be used as a condition in /when directives');
}
return node.value;
case "VariableReference":
try {
const varResult = await evaluate(node, env);
return varResult.value;
} catch (error) {
if (error.message && error.message.includes("Variable not found")) {
return void 0;
}
throw error;
}
case "ExecReference":
const execResult = await evaluate(node, env);
return execResult.value;
case "Text":
return node.content;
default:
const result = await evaluate(node, env);
return result.value;
}
} catch (error) {
throw new MlldDirectiveError(
`Expression evaluation failed: ${error instanceof Error ? error.message : String(error)}`,
"expression",
{
location: node?.location,
cause: error,
context: { nodeType: node?.type, operator: node?.operator },
env
}
);
}
}
__name(evaluateUnifiedExpression, "evaluateUnifiedExpression");
async function evaluateBinaryExpression(node, env) {
let { operator } = node;
if (Array.isArray(operator)) {
operator = operator[0];
}
const leftResult = await evaluateUnifiedExpression(node.left, env);
if (operator === "&&") {
const leftTruthy = isTruthy(leftResult);
if (!leftTruthy) {
return leftResult;
}
const rightResult2 = await evaluateUnifiedExpression(node.right, env);
return rightResult2;
}
if (operator === "||") {
const leftTruthy = isTruthy(leftResult);
if (leftTruthy) {
return leftResult;
}
const rightResult2 = await evaluateUnifiedExpression(node.right, env);
return rightResult2;
}
const rightResult = await evaluateUnifiedExpression(node.right, env);
switch (operator) {
case "==":
const equal = isEqual(leftResult, rightResult);
return equal;
case "!=":
return !isEqual(leftResult, rightResult);
case "~=":
const regex = new RegExp(String(rightResult));
return regex.test(String(leftResult));
case "<":
const leftNum = toNumber(leftResult);
const rightNum = toNumber(rightResult);
const ltResult = leftNum < rightNum;
return ltResult;
case ">":
return toNumber(leftResult) > toNumber(rightResult);
case "<=":
return toNumber(leftResult) <= toNumber(rightResult);
case ">=":
return toNumber(leftResult) >= toNumber(rightResult);
case "+":
return toNumber(leftResult) + toNumber(rightResult);
case "-":
return toNumber(leftResult) - toNumber(rightResult);
case "*":
return toNumber(leftResult) * toNumber(rightResult);
case "/":
return toNumber(leftResult) / toNumber(rightResult);
case "%":
return toNumber(leftResult) % toNumber(rightResult);
default:
throw new Error(`Unknown binary operator: ${operator}`);
}
}
__name(evaluateBinaryExpression, "evaluateBinaryExpression");
async function evaluateUnaryExpression(node, env) {
const operandResult = await evaluateUnifiedExpression(node.operand, env);
switch (node.operator) {
case "!":
return !isTruthy(operandResult);
case "-":
return -toNumber(operandResult);
case "+":
return +toNumber(operandResult);
default:
throw new Error(`Unknown unary operator: ${node.operator}`);
}
}
__name(evaluateUnaryExpression, "evaluateUnaryExpression");
async function evaluateTernaryExpression(node, env) {
const conditionResult = await evaluateUnifiedExpression(node.condition, env);
return isTruthy(conditionResult) ? await evaluateUnifiedExpression(node.trueBranch, env) : await evaluateUnifiedExpression(node.falseBranch, env);
}
__name(evaluateTernaryExpression, "evaluateTernaryExpression");
async function evaluateArrayFilterExpression(node, env) {
const array = await evaluateUnifiedExpression(node.array, env);
if (!Array.isArray(array)) {
throw new Error(`Cannot filter non-array value: ${typeof array}`);
}
const results = [];
for (const item of array) {
const itemEnv = env.withVariable("$", item);
const passes = await evaluateUnifiedExpression(node.filter, itemEnv);
if (passes) {
results.push(item);
}
}
return results;
}
__name(evaluateArrayFilterExpression, "evaluateArrayFilterExpression");
async function evaluateArraySliceExpression(node, env) {
const array = await evaluateUnifiedExpression(node.array, env);
if (!Array.isArray(array)) {
throw new Error(`Cannot slice non-array value: ${typeof array}`);
}
const start = node.start || 0;
const end = node.end !== void 0 ? node.end : array.length;
return array.slice(start, end);
}
__name(evaluateArraySliceExpression, "evaluateArraySliceExpression");
function isUnifiedExpressionNode(node) {
return node && [
"BinaryExpression",
"UnaryExpression",
"TernaryExpression",
"ArrayFilterExpression",
"ArraySliceExpression",
"Literal"
].includes(node.type);
}
__name(isUnifiedExpressionNode, "isUnifiedExpressionNode");
async function evaluateArrayFilter(array, filter, env) {
const results = [];
for (const item of array) {
const itemEnv = env.withVariable("$", item);
const passes = await evaluateUnifiedExpression(filter, itemEnv);
if (passes) results.push(item);
}
return results;
}
__name(evaluateArrayFilter, "evaluateArrayFilter");
export { evaluateArrayFilter, evaluateUnifiedExpression, isUnifiedExpressionNode };
//# sourceMappingURL=expressions-FPH3NB7C.mjs.map
//# sourceMappingURL=expressions-FPH3NB7C.mjs.map