public ZzzNode Traverse(Expression exp)
            {
                var edge = new ExpressionWrapper(exp, false);

                if (!children.TryGetValue(edge, out var child))
                {
                    children.Add(edge, child = new ZzzNode());
                }
                return(child);
            }
        internal static LambdaExpression BuildTreeValidator(this ModelConfigurationNode node, IPathFormatter pathFormatter)
        {
            var allMutators = new Dictionary <ExpressionWrapper, List <MutatorConfiguration> >();

            node.GetMutators(allMutators);

            var root = new ZzzNode();

            foreach (var pair in allMutators)
            {
                var arrays    = GetArrays(node.RootType, pair.Key.Expression, pair.Value);
                var arrayNode = arrays.Aggregate(root, (current, array) => current.Traverse(array));
                arrayNode.mutators.Add(new KeyValuePair <Expression, List <MutatorConfiguration> >(pair.Key.Expression, pair.Value));
            }

            var parameter    = node.Parent == null ? (ParameterExpression)node.Path : Expression.Parameter(node.NodeType, node.NodeType.Name);
            var treeRootType = ValidationResultTreeNodeBuilder.BuildType(parameter.Type);
            var result       = Expression.Parameter(typeof(ValidationResultTreeNode), "tree");
            var priority     = Expression.Parameter(typeof(int), "priority");
            var aliases      = new List <KeyValuePair <Expression, Expression> > {
                new KeyValuePair <Expression, Expression>(parameter, node.Path)
            };

            root = GetArrays(node.RootType, node.Path, new MutatorConfiguration[0]).Aggregate(root, (current, array) => current.Traverse(array));

            var validationResults = new List <Expression>();

            root.BuildValidator(pathFormatter, node, aliases, new Dictionary <ParameterExpression, ExpressionPathsBuilder.SinglePaths>(), result, treeRootType, priority, validationResults);

            //validationResults = validationResults.Select(exp => ExtractLoopInvariantFatExpressions(exp, new []{parameter}, expression => expression)).ToList();
            validationResults = validationResults.SplitToBatches(parameter, result, priority);

            Expression body;

            switch (validationResults.Count)
            {
            case 0:
                body = Expression.Empty();
                break;

            case 1:
                body = validationResults[0];
                break;

            default:
                body = Expression.Block(validationResults);
                break;
            }

            body = body.ExtractLoopInvariantFatExpressions(new[] { parameter }, expression => expression);
            var lambda = Expression.Lambda(body, parameter, result, priority);

            return(lambda);
        }