public static FinalizationResults FinalizeUp(SolvingNode[] toposortedNodes, SolvingNode[] outputNodes) { var typeVariables = new HashSet <SolvingNode>(); var syntaxNodes = new SolvingNode[toposortedNodes.Length]; var namedNodes = new List <SolvingNode>(); void Finalize(SolvingNode node) { if (node.State is RefTo) { var originalOne = node.GetNonReference(); if (originalOne != node) { Console.WriteLine($"\t{node.Name}->r"); node.State = new RefTo(originalOne); } if (originalOne.State is IType) { node.State = originalOne.State; Console.WriteLine($"\t{node.Name}->s"); } } else if (node.State is ICompositeType composite) { if (composite.Members.Any(m => m.State is RefTo)) { node.State = composite.GetNonReferenced(); Console.WriteLine($"\t{node.Name}->ar"); } foreach (var member in composite.Members) { Finalize(member); } } } foreach (var node in toposortedNodes.Reverse()) { Finalize(node); foreach (var member in node.GetAllLeafTypes()) { if (member.Type == SolvingNodeType.TypeVariable && member.State is Constrains) { if (!typeVariables.Contains(member)) { typeVariables.Add(member); } } } if (node.Type == SolvingNodeType.Named) { namedNodes.Add(node); } else if (node.Type == SolvingNodeType.SyntaxNode) { syntaxNodes[int.Parse(node.Name)] = node; } } var outputTypes = outputNodes .SelectMany(s => s.GetAllLeafTypes()) .Distinct() .ToArray(); var notSolved = toposortedNodes .Where(t => t.State is Constrains) .Except(outputTypes) .ToArray(); foreach (var node in notSolved) { node.State = ((Constrains)node.State).TrySolveOrNull() ?? node.State; } return(new FinalizationResults(typeVariables.ToArray(), namedNodes.ToArray(), syntaxNodes)); }