예제 #1
0
        private static bool ExactlyOnce(object[] args, TextBuffer output, BindingEnvironment env, MethodCallFrame predecessor, Step.Continuation k)
        {
            ArgumentCountException.Check("ExactlyOnce", 1, args);
            TextBuffer finalOutput = output;
            BindingList <LogicVariable> finalBindings = null;
            State           finalState = State.Empty;
            MethodCallFrame finalFrame = predecessor;
            bool            failure    = true;

            var chain = Step.ChainFromBody("ExactlyOnce", args);

            chain.Try(output, env,
                      (o, u, d, p) =>
            {
                failure       = false;
                finalOutput   = o;
                finalBindings = u;
                finalState    = d;
                finalFrame    = p;
                return(true);
            },
                      predecessor);

            if (failure)
            {
                var failedCall = (Call)chain;
                throw new CallFailedException(env.Resolve(failedCall.Task), env.ResolveList(failedCall.Arglist));
            }
            return(k(finalOutput, finalBindings, finalState, finalFrame));
        }
예제 #2
0
        private static bool Not(object[] args, TextBuffer o, BindingEnvironment e, MethodCallFrame predecessor, Step.Continuation k)
        {
            foreach (var arg in args)
            {
                if (!Term.IsGround(arg))
                {
                    throw new ArgumentInstantiationException("Not", e, args, "Use NotAny if you intend goals that aren't ground.");
                }
            }
            // Whether the call to args below succeeded
            var success = false;

            // This always fails, since its continuation fails too
            Step.ChainFromBody("Not", args)
            .Try(o, e,
                 (newOut, newE, newK, newP) =>
            {
                // Remember that we succeeded, then fail
                success = true;
                return(false);
            },
                 predecessor);

            // If the call to args succeeded, fail; otherwise call continuation
            return(!success && k(o, e.Unifications, e.State, predecessor));
        }
예제 #3
0
 private static bool IgnoreOutput(object[] args, TextBuffer o, BindingEnvironment e, MethodCallFrame predecessor, Step.Continuation k)
 {
     return(Step.ChainFromBody("IgnoreOutput", args).Try(
                o, e,
                (_, u, s, p) => k(o, u, s, p),
                predecessor));
 }
예제 #4
0
        private static bool NotAny(object[] args, TextBuffer o, BindingEnvironment e, MethodCallFrame predecessor, Step.Continuation k)
        {
            // Whether the call to args below succeeded
            var success = false;

            // This always fails, since its continuation fails too
            Step.ChainFromBody("NotAny", args)
            .Try(o, e,
                 (newOut, newE, newK, newP) =>
            {
                // Remember that we succeeded, then fail
                success = true;
                return(false);
            },
                 predecessor);

            // If the call to args succeeded, fail; otherwise call continuation
            return(!success && k(o, e.Unifications, e.State, predecessor));
        }
예제 #5
0
        private static bool Implies(object[] args, TextBuffer output, BindingEnvironment env, MethodCallFrame predecessor, Step.Continuation k)
        {
            if (args.Length < 2)
            {
                throw new ArgumentCountException(nameof(Implies), 2, args);
            }

            var producer      = args[0];
            var producerChain = Step.ChainFromBody(nameof(Implies), producer);
            var consumer      = args.Skip(1).ToArray();
            var consumerChain = Step.ChainFromBody(nameof(Implies), consumer);

            var dynamicState = env.State;
            var resultOutput = output;
            var allTrue      = true;

            producerChain.Try(resultOutput, env,
                              (o, u, d, p) =>
            {
                // We've got a solution to the producer in u.
                // So run the consumer once with u but not d or o.
                allTrue &= consumerChain.Try(resultOutput,
                                             new BindingEnvironment(env, u, dynamicState),
                                             (o2, u2, d2, newP) =>
                {
                    // Save modifications to dynamic state, output; throw away binding state
                    dynamicState = d2;
                    resultOutput = o2;
                    // Accept this one solution to consumer; don't backtrack it.
                    return(true);
                },
                                             p);
                // Backtrack to generate the next solution for producer
                return(false);
            },
                              predecessor);

            // Use original unifications but accumulated output and state.
            return(allTrue && k(resultOutput, env.Unifications, dynamicState, predecessor));
        }
예제 #6
0
 /// <summary>
 /// Calls all the tasks in the body and allows the user to provide their own continuation.
 /// The only (?) use case for this is when you want to forcibly generate multiple solutions
 /// </summary>
 internal static void GenerateSolutionsFromBody(string callingTaskName, object[] body, TextBuffer o, BindingEnvironment e,
                                                Step.Continuation k,
                                                MethodCallFrame predecessor)
 {
     Step.ChainFromBody(callingTaskName, body).Try(o, e, k, predecessor);
 }
예제 #7
0
 private static bool And(object[] args, TextBuffer o, BindingEnvironment e, MethodCallFrame predecessor, Step.Continuation k)
 => Step.ChainFromBody("And", args).Try(o, e, k, predecessor);