Esempio n. 1
0
 /// <inheritdoc />
 public override bool Call(object[] arglist, TextBuffer output, BindingEnvironment env, MethodCallFrame predecessor, Step.Continuation k)
 => implementation(env.ResolveList(arglist)) && k(output, env.Unifications, env.State, predecessor);
Esempio n. 2
0
 /// <inheritdoc />
 public override bool Call(object[] arglist, TextBuffer output, BindingEnvironment env, MethodCallFrame predecessor, Step.Continuation k)
 {
     ArgumentCountException.Check(Name, 0, arglist);
     return(implementation() &&
            k(output, env.Unifications, env.State, predecessor));
 }
Esempio n. 3
0
 /// <summary>
 /// Call this task with the specified arguments
 /// </summary>
 /// <param name="arglist">Task arguments</param>
 /// <param name="output">Output accumulated so far</param>
 /// <param name="env">Binding environment</param>
 /// <param name="predecessor">Most recently succeeded MethodCallFrame</param>
 /// <param name="k">Continuation</param>
 /// <returns>True if task succeeded and continuation succeeded</returns>
 /// <exception cref="CallFailedException">If the task fails</exception>
 public abstract bool Call(object[] arglist, TextBuffer output, BindingEnvironment env,
                           MethodCallFrame predecessor, Step.Continuation k);
Esempio n. 4
0
        /// <summary>
        /// Call this task with the specified arguments
        /// </summary>
        /// <param name="arglist">Task arguments</param>
        /// <param name="output">Output accumulated so far</param>
        /// <param name="env">Binding environment</param>
        /// <param name="predecessor">Most recently succeeded MethodCallFrame</param>
        /// <param name="k">Continuation</param>
        /// <returns>True if task succeeded and continuation succeeded</returns>
        /// <exception cref="CallFailedException">If the task fails</exception>
        public override bool Call(object[] arglist, TextBuffer output, BindingEnvironment env, MethodCallFrame predecessor, Step.Continuation k)
        {
            string lastToken = null;

            if (Suffix)
            {
                (lastToken, output) = output.Unappend();
                arglist             = new object[] { lastToken };
            }

            ArgumentCountException.Check(this, this.ArgCount, arglist);
            var successCount = 0;

            if (ReadCache)
            {
                // Check for a hit in the cache.  If we find one, we're done.
                if (Cache.TryGetValue(env.State, arglist, out var result))
                {
                    if (result.Success)
                    {
                        if (Function)
                        {
                            // We got a hit, and since this is a function, it's the only allowable hit.
                            // So we succeed deterministically.
                            return(env.Unify(arglist[arglist.Length - 1], result.FunctionValue,
                                             out BindingList <LogicVariable> u) &&
                                   k(output.Append(result.Text), u, env.State, predecessor));
                        }
                        else
                        {
                            successCount++;
                            if (k(output.Append(result.Text), env.Unifications, env.State, predecessor))
                            {
                                return(true);
                            }
                        }
                    }
                    else
                    {
                        // We have a match on a cached fail result, so force a failure, skipping over the methods.
                        goto failed;
                    }
                }
                else if (arglist.Any(x => x is LogicVariable))
                {
                    foreach (var pair in Cache.Bindings(env.State))
                    {
                        if (pair.Value.Success &&
                            env.UnifyArrays((object[])pair.Key, arglist,
                                            out BindingList <LogicVariable> unifications))
                        {
                            successCount++;
                            if (k(output.Append(pair.Value.Text), unifications, env.State, predecessor))
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            if (ContainsCoolStep)
            {
                var s = env.State;
                s   = CallCounts.SetItem(s, this, CallCount(s) + 1);
                env = new BindingEnvironment(env, env.Unifications, s);
            }

            var methods = this.EffectiveMethods;

            for (var index = 0; index < methods.Count && !(this.Deterministic && successCount > 0); index++)
            {
                var method = methods[index];
                if (method.Try(arglist, output, env, predecessor,
                               (o, u, s, newPredecessor) =>
                {
                    successCount++;
                    if (WriteCache)
                    {
                        var final = env.ResolveList(arglist, u);
                        if (Term.IsGround(final))
                        {
                            s = StoreResult(s, final, new CachedResult(true,
                                                                       Function?final[final.Length - 1]:null,
                                                                       TextBuffer.Difference(output, o)));
                        }
                    }
                    return(k(o, u, s, newPredecessor));
                }))
                {
                    return(true);
                }
                if (Suffix)
                {
                    // Undo any overwriting that the method might have done
                    output.Buffer[output.Length - 1] = lastToken;
                }
            }

failed:
            var currentFrame = MethodCallFrame.CurrentFrame = env.Frame;

            if (currentFrame != null)
            {
                currentFrame.BindingsAtCallTime = env.Unifications;
            }
            if (successCount == 0 && this.MustSucceed)
            {
                throw new CallFailedException(this, arglist);
            }

            if (currentFrame != null)
            {
                env.Module.TraceMethod(Module.MethodTraceEvent.CallFail, currentFrame.Method, currentFrame.Arglist, output,
                                       env);
                MethodCallFrame.CurrentFrame = currentFrame.Predecessor;
            }

            // Failure
            return(false);
        }
Esempio n. 5
0
 /// <summary>
 /// Attempt to run this step.
 /// </summary>
 /// <param name="output">Output accumulated so far</param>
 /// <param name="e">Variable binding information to use in this step</param>
 /// <param name="k">Procedure to run if this step and the other steps in its chain are successful</param>
 /// <param name="predecessor">Predecessor frame</param>
 /// <returns>True if all steps in the chain, and the continuation are all successful.  False means we're backtracking</returns>
 public abstract bool Try(TextBuffer output, BindingEnvironment e, Continuation k, MethodCallFrame predecessor);
        /// <inheritdoc />
        public override bool Call(object[] args, TextBuffer buffer, BindingEnvironment env, MethodCallFrame predecessor, Step.Continuation k)
        {
            ArgumentCountException.Check(Name, 1, args);
            var arg  = env.Resolve(args[0]);
            var text = arg as string[];

            if (buffer.WriteMode)
            {
                if (text == null)
                {
                    text = renderer(arg);
                }

                return(k(buffer.Append(text), env.Unifications, env.State, predecessor));
            }

            // Read mode
            if (arg is LogicVariable l)
            {
                var token = buffer.NextToken(out var newBuffer);
                if (token == null)
                {
                    return(false);
                }
                object value = token;
                switch (token)
                {
                case "null":
                    value = null;
                    break;

                case "true":
                    value = true;
                    break;

                case "false":
                    value = false;
                    break;

                default:
                    if (int.TryParse(token, out var iValue))
                    {
                        value = iValue;
                    }
                    else if (float.TryParse(token, out var fValue))
                    {
                        value = fValue;
                    }
                    break;
                }
                return(k(newBuffer,
                         BindingList <LogicVariable> .Bind(env.Unifications, l, value),
                         env.State, predecessor));
            }

            if (text == null)
            {
                text = renderer(arg);
            }
            return(buffer.Unify(text, out var result) &&
                   k(result, env.Unifications, env.State, predecessor));
        }
Esempio n. 7
0
 /// <inheritdoc />
 public override bool Call(object[] arglist, TextBuffer output, BindingEnvironment env, MethodCallFrame predecessor, Step.Continuation k)
 {
     return(k(output.Append(implementation(arglist, output, env, predecessor)),
              env.Unifications, env.State, predecessor));
 }