using System; using System.Collections.Generic; namespace HeuristicLab.Problems.ProgramSynthesis.Push.Data.Tree { using System.Linq; using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions; public static class TreeExtensions { private static readonly Expression ExecNoop = ExpressionTable.GetStatelessExpression(); private static readonly Expression CodeNoop = ExpressionTable.GetStatelessExpression(); public static TreeNode ToTree( this IEnumerable items, Predicate isChild, Func> childrenResolver) { var tree = new TreeNode(); foreach (var item in items) { if (isChild(item)) { var subNode = childrenResolver(item).ToTree(isChild, childrenResolver); subNode.Value = item; tree.AddNode(subNode); } else { tree.Add(item); } } return tree; } public static IEnumerable> DepthLast(this TreeNode node) { foreach (var child in node.Children) { if (child.Children.Count > 0) { foreach (var subChild in child.DepthLast()) { yield return subChild; } } else yield return child; } yield return node; } public static IEnumerable DepthLast(this TreeNode node, Func, T> resolveParent) { foreach (var child in node.Children) { if (child.Children.Count > 0) { var subExpressions = child.DepthLast(resolveParent); yield return resolveParent(subExpressions); } else yield return child.Value; } } public static PushProgram ToPushProgramWithoutNoopExpressions(this TreeNode tree) { return ToPushProgram(tree, e => !ReferenceEquals(e, ExecNoop) && !ReferenceEquals(e, CodeNoop)); } public static PushProgram ToPushProgram(this TreeNode tree, Func condition = null) { // wrap into program as depthlast expects that tree represents program and not a single expression if (tree.Count == 1) { var tmp = tree; tree = new TreeNode(); tree.AddNode(tmp); } var expressions = tree.DepthLast(e => ResolveProgram(e, condition)); return ResolveProgram(expressions, condition); } public static TreeNode ToTree(this PushProgram program) { var tree = program.Expressions.ToTree(e => e.IsProgram, e => ((PushProgram)e).Expressions); tree.Value = program; return tree; } private static PushProgram ResolveProgram(IEnumerable expressions, Func condition = null) { if (condition != null) { expressions = expressions.Where(condition); } return new PushProgram(expressions.ToList()); } } }