/** * Expression simplification based on context. */ import { Expression } from './expression.js'; import { Context } from './context.js'; /** * Simplify an expression based on the context. */ export function simplify(expr: Expression, context: Context): Expression { let current = expr; let previous: Expression | null = null; // Keep applying simplification rules until no more changes while (previous === null || !current.equals(previous)) { previous = current; current = applySimplificationRules(current, context); } return current; } /** * Apply simplification rules once. */ function applySimplificationRules(expr: Expression, context: Context): Expression { // Rule: left(h) → a if h has type and(a, b) if (expr.name === 'left' && expr.children.length === 1) { const arg = expr.children[0]; const argType = getTypeOfExpr(arg, context); if (argType && argType.name === 'and' && argType.children.length === 2) { return argType.children[0]; } } // Rule: right(h) → b if h has type and(a, b) if (expr.name === 'right' && expr.children.length === 1) { const arg = expr.children[0]; const argType = getTypeOfExpr(arg, context); if (argType && argType.name === 'and' && argType.children.length === 2) { return argType.children[1]; } } // Recursively simplify children const simplifiedChildren = expr.children.map(child => applySimplificationRules(child, context) ); return new Expression(expr.name, simplifiedChildren); } /** * Get the type of an expression from the context. */ function getTypeOfExpr(expr: Expression, context: Context): Expression | null { // Simple case: variable name lookup if (expr.children.length === 0) { return context.getVariableType(expr.name) || null; } return null; }