public bool Resolve(XPredicate target, IXExpression expression, out List <XPredicate> facts, out List <XPredicate> localFacts)
        {
            if (expression == null)
            {
                facts      = new List <XPredicate>();
                localFacts = new List <XPredicate>();

                return(true);
            }

            switch (expression.Type)
            {
            case XOperand.Predicate:
                var predicateExp = expression as XExpression;
                facts = new List <XPredicate>();

                if (Run(predicateExp.Predicate, out localFacts))
                {
                    foreach (var f in localFacts)
                    {
                        var clone = target.Clone();

                        for (int i = 0; i < f.Vars.Length; ++i)
                        {
                            var sArg = predicateExp.Predicate.Vars[i];
                            var dArg = f.Vars[i];

                            if (sArg.Type == XType.Var && dArg.Type == XType.Const)
                            {
                                clone.Bind(sArg, dArg);
                            }
                        }

                        facts.Add(clone);
                    }

                    return(true);
                }

                return(false);

            case XOperand.Not:
                var notExp = expression as XNot;
                return(!Resolve(target, notExp.Expression.Clone(), out facts, out localFacts));

            default:
                var andExp = expression as XAnd;
                return(Resolve2(target, andExp, out facts, out localFacts));
            }
        }
        public bool Run(XPredicate target, out List <XPredicate> solutions)
        {
            logger.LogD("Target: {0}", target);
            solutions = new List <XPredicate>();

            if (!VerifySignature(target.Signature))
            {
                logger.LogD("FAILED");
                return(false);
            }

            foreach (var c in Database.Clauses)
            {
                var clause = c.Bind(target.Clone());

                if (clause != null)
                {
                    logger.LogD("Suitable clause: {0}", clause);
                    ++logger.Indent;
                    var newTarget = clause.Predicate;

                    if (Resolve(newTarget, clause.Body, out List <XPredicate> partialSolutions, out _))
                    {
                        if (clause.Body == null && !solutions.Contains(newTarget))
                        {
                            solutions.Add(newTarget);
                        }
                        else
                        {
                            solutions.AddRange(partialSolutions);
                        }
                    }

                    --logger.Indent;
                }
            }

            if (solutions.Count != 0)
            {
                logger.LogD("SUCCESS");
                return(true);
            }

            logger.LogD("FAILED");
            return(false);
        }