import { Expression } from './expressions.js'; function booleanAssignments(variables) { const results = []; for (let bits = 1 << variables.length; bits--;) { const assignments = new Map(); for (let index = variables.length; index--;) { assignments.set(variables[index].name, ((bits >> index) & 1) !== 0); } results.push(assignments); } return results; } function matches(expression, semantics, variables) { for (const assignments of booleanAssignments(variables)) { if (expression.evaluate(assignments) !== semantics(assignments)) { return false; } } return true; } function expressionsOfSize(environment, operatorCount) { const results = []; if (operatorCount === 0) { for (const variable of environment.variables) { results.push(variable); } } else { for (const operator of environment.unaryOperators) { for (const subexpression of expressionsOfSize(environment, operatorCount - 1)) { results.push(new Expression(operator, [subexpression])); } } for (let leftOperatorCount = 0; leftOperatorCount < operatorCount; ++leftOperatorCount) { const rightOperatorCount = operatorCount - leftOperatorCount - 1; for (const operator of environment.binaryOperators) { for (const leftSubexpression of expressionsOfSize(environment, leftOperatorCount)) { for (const rightSubexpression of expressionsOfSize(environment, rightOperatorCount)) { results.push(new Expression(operator, [leftSubexpression, rightSubexpression])); } } } } } return results; } function expressionsUpToSize(environment, maximumOperatorCount) { const results = []; for (const operator of environment.nullaryOperators) { results.push(new Expression(operator, [])); } for (let operatorCount = 0; operatorCount <= maximumOperatorCount; ++operatorCount) { results.push(...expressionsOfSize(environment, operatorCount)); } return results; } export function simplify(semantics, environment, maximumOperatorCount) { for (const expression of expressionsUpToSize(environment, maximumOperatorCount)) { if (matches(expression, semantics, environment.variables)) { return expression; } } return undefined; }