public IEnumerable <IAssignmentLiteral> Flatten() { // Start by flattening all of the parameters var flattenedParameters = _parameters.Select(param => param.Flatten().ToArray()).ToArray(); // Get the list of variables that the parameters are assigned to var parameterTargets = flattenedParameters.Select(list => list.First().Variable); // Merge any parameter assignments that assign to the same value var eliminator = new AssignmentEliminator(flattenedParameters.SelectMany(item => item)); eliminator.Eliminate(); parameterTargets = parameterTargets.Select(eliminator.MapVariable); // Generate the assignment for this term var target = new Variable(); yield return(new TermAssignment(target, new BoundFunctor(_unbound, parameterTargets))); // Generate the list of parameter assignments foreach (var param in eliminator.Assignments) { yield return(param); } }
/// <summary> /// Substitutes any variable assignments with their bindings /// </summary> public static IEnumerable <IAssignmentLiteral> BindVariables(this IEnumerable <IAssignmentLiteral> withVariables, IBindings bindings) { var result = new List <IAssignmentLiteral>(); var extras = new List <IAssignmentLiteral>(); // Run through the assignments foreach (var assignment in withVariables) { if (assignment.Value.UnificationKey == null) { // Value is a variable (unifies with everything) var boundTo = bindings.GetValueForVariable(assignment.Value); if (boundTo != null) { // Flatten the bound value var flattened = boundTo.Flatten().ToArray(); // Assign the target value of the bound value to the original value location // Ie, here we have Xn = V and the first value of flattened describes the value of V // in the form Xm = a(...) // Substitute Xn = a(...) in the assignment list // Value of V after resolution can be updated by reading Xn after resolution var first = (IAssignmentLiteral)flattened[0].RebuildWithParameters(new[] { assignment.Variable, flattened[0].Value }); result.Add(first); // Add in any extra variables generated by flattening extras.AddRange(flattened.Skip(1)); } else { // Variable is unbound result.Add(assignment); } } else { result.Add(assignment); } } // Remove any extra items to generate the final result var eliminator = new AssignmentEliminator(result.Concat(extras)); eliminator.Eliminate(); return(eliminator.Assignments); }