Example #1
0
        internal static IEnumerable <bool> UnifyArraysFast(object[] a1, object[] a2, PrologContext context)
        {
            int mark = context.MarkTrace();

            if (UnifyArrays(a1, a2, context))
            {
                yield return(false);
            }
            context.RestoreVariables(mark);
        }
Example #2
0
        private IEnumerable <CutState> EnumerateArg1Driver(LogicVariable arg1, T2 arg2, PrologContext context)
        {
            int tracePointer = context.MarkTrace();

            foreach (var newValue in arg1Enumerator(arg2))
            {
                arg1.UnifyWithAtomicConstant(newValue, context);

                yield return(CutState.Continue);

                context.RestoreVariables(tracePointer);
            }
        }
Example #3
0
        private IEnumerable <CutState> EnumerateBothDriver(LogicVariable arg1, LogicVariable arg2, PrologContext context)
        {
            int tracePointer = context.MarkTrace();

            foreach (var pair in doubleEnumerator())
            {
                arg1.UnifyWithAtomicConstant(pair.Arg1, context);
                arg2.UnifyWithAtomicConstant(pair.Arg2, context);

                yield return(CutState.Continue);

                context.RestoreVariables(tracePointer);
            }
        }
Example #4
0
        /// <summary>
        /// Tests clauses in a randomized order (but still exhaustively).
        /// Uses Shuffler to generate a random permutation.
        /// </summary>
        IEnumerable <CutState> TestShuffledClauses(object[] args, PrologContext context, ushort myFrame)
        {
            entriesListUsed = true;
            var mark        = context.MarkTrace();
            var shuffler    = new Shuffler((ushort)Entries.Count);
            var argIndexers = PredicateArgumentIndexer.ArglistIndexers(args);

            while (!shuffler.Done)
            {
                var entry = Entries[shuffler.Next()];
                if (entry.Prematch(argIndexers))
                {
                    // This shouldn't be here...
                    //context.PushGoalStack(Name, args, myFrame);
                    context.SetCurrentRule(entry);
                    foreach (var cutState in entry.Prove(args, context, myFrame))
                    {
                        if (cutState == CutState.ForceFail)
                        {
                            if (KnowledgeBase.Trace || Trace)
                            {
                                context.TraceOutput("Cut: {0}", new Structure(Name, args));
                            }
                            goto fail;
                        }
                        if (KnowledgeBase.Trace || Trace)
                        {
                            context.TraceOutput("Succeed: {0}", new Structure(Name, args));
                        }
                        yield return(CutState.Continue);

                        if (KnowledgeBase.Trace || Trace)
                        {
                            context.TraceOutput("Retry: {0}", new Structure(Name, args));
                        }
                    }
                }
            }
fail:
            context.RestoreVariables(mark);
            if (KnowledgeBase.Trace || Trace)
            {
                context.TraceOutput("Fail: {0}", new Structure(Name, args));
            }
            //context.UnwindStack(Name, args);
            context.UnwindStack(myFrame);
        }
Example #5
0
        /// <summary>
        /// Tests clauses in the order they appear in the database.
        /// </summary>
        IEnumerable <CutState> TestClausesInOrder(object[] args, PrologContext context, ushort myFrame)
        {
            var mark        = context.MarkTrace();
            var argIndexers = PredicateArgumentIndexer.ArglistIndexers(args);

            entriesListUsed = true;
            foreach (var entry in Entries)
            {
                if (entry.Prematch(argIndexers))
                {
                    context.SetCurrentRule(entry);
                    foreach (var cutState in entry.Prove(args, context, myFrame))
                    {
                        if (cutState == CutState.ForceFail)
                        {
                            if (KnowledgeBase.Trace || Trace)
                            {
                                context.TraceOutput("Cut: {0}", new Structure(Name, args));
                            }
                            goto fail;
                        }
                        if (KnowledgeBase.Trace || Trace)
                        {
                            context.TraceOutput("Succeed: {0}", new Structure(Name, args));
                        }
                        yield return(CutState.Continue);

                        if (KnowledgeBase.Trace || Trace)
                        {
                            context.TraceOutput("Retry: {0}", new Structure(Name, args));
                        }
                    }
                }
            }
fail:
            context.RestoreVariables(mark);
            if (KnowledgeBase.Trace || Trace)
            {
                context.TraceOutput("Fail: {0}", new Structure(Name, args));
            }
            //context.UnwindStack(Name, args);
            context.UnwindStack(myFrame);
        }
Example #6
0
 internal static IEnumerable<bool> UnifyArraysFast(object[] a1, object[] a2, PrologContext context)
 {
     int mark = context.MarkTrace();
     if (UnifyArrays(a1, a2, context))
         yield return false;
     context.RestoreVariables(mark);
 }
Example #7
0
 /// <summary>
 /// Tests clauses in a randomized order (but still exhaustively).
 /// Uses Shuffler to generate a random permutation.
 /// </summary>
 IEnumerable<CutState> TestShuffledClauses(object[] args, PrologContext context, ushort myFrame)
 {
     entriesListUsed = true;
     var mark = context.MarkTrace();
     var shuffler = new Shuffler((ushort)Entries.Count);
     var argIndexers = PredicateArgumentIndexer.ArglistIndexers(args);
     while (!shuffler.Done)
     {
         var entry = Entries[shuffler.Next()];
         if (entry.Prematch(argIndexers))
         {
             // This shouldn't be here...
             //context.PushGoalStack(Name, args, myFrame);
             context.SetCurrentRule(entry);
             foreach (var cutState in entry.Prove(args, context, myFrame))
             {
                 if (cutState == CutState.ForceFail)
                 {
                     if (KnowledgeBase.Trace || Trace)
                         context.TraceOutput("Cut: {0}", new Structure(Name, args));
                     goto fail;
                 }
                 if (KnowledgeBase.Trace || Trace)
                     context.TraceOutput("Succeed: {0}", new Structure(Name, args));
                 yield return CutState.Continue;
                 if (KnowledgeBase.Trace || Trace)
                     context.TraceOutput("Retry: {0}", new Structure(Name, args));
             }
         }
     }
     fail:
     context.RestoreVariables(mark);
     if (KnowledgeBase.Trace || Trace)
         context.TraceOutput("Fail: {0}", new Structure(Name, args));
     //context.UnwindStack(Name, args);
     context.UnwindStack(myFrame);
 }
Example #8
0
 /// <summary>
 /// Tests clauses in the order they appear in the database.
 /// </summary>
 IEnumerable<CutState> TestClausesInOrder(object[] args, PrologContext context, ushort myFrame)
 {
     var mark = context.MarkTrace();
     var argIndexers = PredicateArgumentIndexer.ArglistIndexers(args);
     entriesListUsed = true;
     foreach (var entry in Entries)
     {
         if (entry.Prematch(argIndexers))
         {
             context.SetCurrentRule(entry);
             foreach (var cutState in entry.Prove(args, context, myFrame))
             {
                 if (cutState == CutState.ForceFail)
                 {
                     if (KnowledgeBase.Trace || Trace)
                         context.TraceOutput("Cut: {0}", new Structure(Name, args));
                     goto fail;
                 }
                 if (KnowledgeBase.Trace || Trace)
                     context.TraceOutput("Succeed: {0}", new Structure(Name, args));
                 yield return CutState.Continue;
                 if (KnowledgeBase.Trace || Trace)
                     context.TraceOutput("Retry: {0}", new Structure(Name, args));
             }
         }
     }
     fail:
     context.RestoreVariables(mark);
     if (KnowledgeBase.Trace || Trace)
         context.TraceOutput("Fail: {0}", new Structure(Name, args));
     //context.UnwindStack(Name, args);
     context.UnwindStack(myFrame);
 }
Example #9
0
        private const byte NoRegister      = 0xff;            // Target register meaning not to write to register

        // So here's append([], X, X). :
        //    MatchLiteral([], 0)
        //    MatchVarFirst(1)               % This is actually a no-op
        //    MatchVar(1, 2)
        //    Return
        //
        // And here's append([H|T], X, [H|T1]) :- append(T, X, T1).
        //    MatchStructure(dot, 2, L1, 0)
        //    MatchVarFirst(0>0>3)      % H is at 3
        //    MatchVarFirst(0>1>4)      % T is at 4
        // L1 MatchVarFirst(1)               % Actually a no-op
        //    MatchStructure(dot, 2, L2, 2)
        //    MatchVar(3, 2>0)
        //    MatchVarFirst(5, 2>1)        % T1 is at 5
        // L2 Call(6, Fail, Succeed, append/3, register(4), register(2), register(5))
        #endregion

        #region Interpreter
        internal IEnumerable <CutState> StackCall(PrologContext context)
        {
            int traceMark = context.MarkTrace();
            // On entry, the stack pointer points at the base of our arguments.
            int    framePointer        = context.MakeFrame(frameSize);
            ushort pc                  = 0;
            ushort writeModeEndAddress = 0; // We're in write mode if pc < writeModeEndAddress.
// ReSharper disable TooWideLocalVariableScope
            // Resharper is confused - can't move this inside the while loop, or its lifetime changes.
            ushort endOfBuilds;         // PC of last call instruction whose arguments have been built.

// ReSharper restore TooWideLocalVariableScope

            while (true)
            {
                switch ((Opcode)code[pc++])
                {
                    #region Head opcodes
                case Opcode.MatchLiteral:
                {
                    object literal = GetLiteral(ref pc);
                    if (pc < writeModeEndAddress)
                    {
                        // Write mode
                        SetOperand(context, framePointer, ref pc, literal);
                    }
                    else
                    {
                        // Read mode
                        if (!Term.Unify(DecodeOperand(context, framePointer, ref pc), literal, context))
                        {
                            goto fail;
                        }
                    }
                }
                break;

                case Opcode.MatchVarFirst:
                {
                    if (pc < writeModeEndAddress)
                    {
                        // Write mode
                        Symbol name     = GetSymbol(ref pc);
                        int    register = code[pc++];
                        var    l        = new LogicVariable(name);
                        SetOperand(context, framePointer, ref pc, l);
                        if (register != NoRegister)
                        {
                            context.SetStack(framePointer, register, l);
                        }
                    }
                    else
                    {
                        pc += 2;         // Skip over variable name.
                        int register = code[pc++];
                        // Read mode
                        object operand = DecodeOperand(context, framePointer, ref pc);
                        if (register != NoRegister)
                        {
                            context.SetStack(framePointer, register, operand);
                        }
                    }
                }
                break;

                case Opcode.MatchVar:
                {
                    object register = Register(context, framePointer, pc++);
                    if (pc < writeModeEndAddress)
                    {
                        // Write mode
                        SetOperand(context, framePointer, ref pc, register);
                    }
                    else
                    {
                        // Read mode
                        if (!Term.Unify(DecodeOperand(context, framePointer, ref pc), register, context))
                        {
                            goto fail;
                        }
                    }
                }
                break;

                case Opcode.MatchStructure:
                {
                    Symbol functor    = GetSymbol(ref pc);
                    int    arity      = code[pc++];
                    ushort endAddress = GetUShort(ref pc);

                    if (pc < writeModeEndAddress)
                    {
                        // Write mode
                        SetOperand(context, framePointer, ref pc, new Structure(functor, new object[arity]));
                    }
                    else
                    {
                        // Read mode
                        object arg = DecodeOperand(context, framePointer, ref pc);
                        var    s   = arg as Structure;
                        if (s == null || !s.IsFunctor(functor, arity))
                        {
                            var l = arg as LogicVariable;
                            if (l == null)
                            {
                                goto fail;
                            }
                            l.UnifyWithStructure(new Structure(functor, new object[arity]));
                            writeModeEndAddress = endAddress;
                        }
                    }
                }
                break;
                    #endregion

                    #region Body opcodes: structure building
                case Opcode.BuildStructure:
                {
                    Symbol functor = GetSymbol(ref pc);
                    int    arity   = code[pc++];
                    SetOperand(context, framePointer, ref pc,
                               new Structure(functor, new object[arity]));
                }
                break;

                case Opcode.BuildLiteral:
                    SetOperand(context, framePointer, ref pc, GetLiteral(ref pc));
                    break;

                case Opcode.BuildVar:
                {
                    Symbol name = GetSymbol(ref pc);
                    SetOperand(context, framePointer, ref pc, new LogicVariable(name));
                }
                break;

                case Opcode.BuildReg:
                    object registerValue = Register(context, framePointer, pc++);
                    SetOperand(context, framePointer, ref pc, registerValue);
                    break;
                    #endregion

                    #region Body: control flow
                case Opcode.CallWokenGoals:
                case Opcode.Call:
                case Opcode.CallPrimitive:
                    endOfBuilds = pc;
                    // ReSharper disable once InconsistentNaming
                    ushort succeedPC;
                    IEnumerator <CutState> iterator;
                    var failPC = StartCallInstruction(context, framePointer, ref pc, out succeedPC, out iterator);
                    while (true)
                    {
                        if (iterator == null || iterator.MoveNext())
                        {
                            // Call succeeds
                            if (succeedPC == SuccessContinuationPC)
                            {
                                yield return(CutState.Continue);

                                // If we get here, then our caller is requesting a redo
                                // Fall through and continue this iterator.
                                if (iterator == null)
                                {
                                    goto fail;                     // Kluge: special case to handle CallWokenGoals instruction where there are no woken goals.
                                }
                            }
                            else
                            {
                                if (succeedPC > endOfBuilds)
                                {
                                    // Haven't run the build instructions for next goal, so break out and run them.
                                    break;
                                }
                                pc = (ushort)(succeedPC + 1);   // StartCallInstruction assumes we've skipped over the opcode.
                                // succeedPC is address of call/callprimitive instruction; next byte is iterator register
                                failPC = this.StartCallInstruction(context, framePointer, ref pc, out succeedPC, out iterator);
                                // Continue while loop
                            }
                        }
                        else
                        {
                            // Call fails
                            switch (failPC)
                            {
                            case FailContinuationPC:
                                goto fail;

                            case CutContinuationPC:
                                goto cut;

                            default:
                                // failPC is address of call/callprimitive instruction; next byte is iterator register
                                pc       = (ushort)(failPC + 1);    // +1 because we're skipping over the opcode
                                iterator =
                                    (IEnumerator <CutState>)context.GetStack(framePointer, code[pc++]);
                                if (iterator == null)          // Kluge: special case to handle CallWokenGoals instruction where there are no woken goals.
                                {
                                    goto fail;
                                }

                                failPC    = GetUShort(ref pc);
                                succeedPC = GetUShort(ref pc);
                                break;
                            }
                        }
                    }
                    break;
                    #endregion

                default:
                    Debug.Assert(false, "Bad opcode in byte compiled Prolog rule, pc=" + (pc - 1) + ", opcode=" + ((Opcode)code[pc - 1]));
                    break;
                }
            }

            // The while loop above never terminates normally; it only yeilds or branches to one of the following labels
cut:
            context.PopFrame(framePointer);
            context.RestoreVariables(traceMark);
            yield return(CutState.ForceFail);

fail:
            context.PopFrame(framePointer);
            context.RestoreVariables(traceMark);
        }