Ejemplo n.º 1
0
        private void WalkGoal(KnowledgeBase kb, KnowledgeBaseRule rule, object goal)
        {
            goal = Term.Deref(goal);
            var atom = goal as Symbol;

            if (atom != null)
            {
                var p = new PredicateIndicator(atom, 0);
                if (PrologPrimitives.IsDefined(p))
                {
                    return;
                }
                var predicate = kb.CheckForPredicateInfo(p);
                if (predicate == null)
                {
                    rule.PrintWarning("undefined predicate {0}", p);
                }
                else
                {
                    MarkReferenced(predicate);
                }
            }
            else
            {
                var s = goal as Structure;
                if (s != null)
                {
                    WalkGoal(kb, rule, s);
                }
                else if (!(goal is LogicVariable) && !(goal is bool))
                {
                    rule.PrintWarning("malformed goal: {0}", goal);
                }
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Adds a new user-defined binary primitive predicate given
 /// C# delegates to implement its different modes.  Assumes
 /// arguments are always atomic, and that the relation won't
 /// be called with the same unbound variable for both arguments.
 /// </summary>
 /// <param name="name">Name to give to the predicate</param>
 /// <param name="documentation">Description of the operation of the predicate</param>
 /// <param name="arg1Name">Name of the first argument (for documentation and error messages)</param>
 /// <param name="arg2Name">Name of hte second argument (for documentation and error messages)</param>
 /// <param name="filter">Implementation of predicate for case where both arguments are instantiated.</param>
 /// <param name="arg1Enumerator">For non-left-unique predicates: implementation for case where only the second argument is instantiated, so the values of the first argument must be enumerated.</param>
 /// <param name="arg1Function">For left-unique predicates: implementation for the case where only the second argument is instantiated, so need to compute the value of the first (if any).</param>
 /// <param name="arg2Enumerator">For non-right-unique predicates: implementation for case where only the first argument is instantiated, so the values of the second argument must be enumerated.</param>
 /// <param name="arg2Function">For right-unique predicates: implementation for the case where only the first argument is instantiated, so need to compute the value of the second (if any)</param>
 /// <param name="doubleEnumerator">Implementation of the case where neither argument is instantiated.</param>
 public static void Declare(
     string name,
     string documentation,
     string arg1Name,
     string arg2Name,
     Filter filter,
     Arg1Enumerator arg1Enumerator     = null,
     Arg1Function arg1Function         = null,
     Arg2Enumerator arg2Enumerator     = null,
     Arg2Function arg2Function         = null,
     DoubleEnumerator doubleEnumerator = null)
 {
     PrologPrimitives.DefinePrimitive(
         Symbol.Intern(name),
         new BinaryPrimitive <T1, T2>(
             name,
             arg1Name,
             arg2Name,
             filter,
             arg1Enumerator,
             arg1Function,
             arg2Enumerator,
             arg2Function,
             doubleEnumerator).BinaryPrimitiveImplementation,
         null,
         documentation,
         arg1Name,
         arg2Name);
 }
Ejemplo n.º 3
0
 /// <summary>
 /// True if the specified functor/arity is undefined.
 /// </summary>
 public bool Undefined(PredicateIndicator p)
 {
     if (PrologPrimitives.IsDefined(p))
         return false;
     if (CheckForPredicateInfoInThisKB(p) != null)
         return false;
     foreach (KnowledgeBase import in imports)
         if (!import.Undefined(p))
             return false;
     return true;
 }
Ejemplo n.º 4
0
        private ushort StartCallInstruction(PrologContext context, int framePointer, ref ushort pc, out ushort succeedPC,
                                            out IEnumerator <CutState> iterator)
        {
            int    iteratorRegister = code[pc++];
            ushort failPC           = GetUShort(ref pc);

            succeedPC = GetUShort(ref pc);
            iterator  = null;
            // Make the iterator.  How we do this depends on the opcode, so re-fetch it.
            switch ((Opcode)code[pc - CallTargetOffset])
            {
            case Opcode.CallWokenGoals:
            {
                if (context.GoalsHaveWoken)
                {
                    iterator = context.ProveAllWokenGoals().GetEnumerator();
                }
            }
            break;

            case Opcode.Call:
            {
                // It's a user-defined predicate call
                PredicateInfo calledPredicate = GetPredicate(ref pc);
                PushCallArgs(context, framePointer, predicate.Arity, ref pc);
                iterator = calledPredicate.StackCall(context).GetEnumerator();
            }
            break;

            case Opcode.CallPrimitive:
            {
                // It's a primitive call
                PrologPrimitives.PrimitiveImplementation implementation = GetPrimitive(ref pc);
                int arity = code[pc++];
                PushCallArgs(context, framePointer, arity, ref pc);
                iterator =
                    PrologPrimitives.StackCall(implementation, arity, context).GetEnumerator();
            }
            break;

            default:
                Debug.Assert(false, "Bad call opcode");
                break;
            }
            context.SetStack(framePointer, iteratorRegister, iterator);
            return(failPC);
        }
Ejemplo n.º 5
0
 /// <summary>
 /// True if the specified functor/arity is undefined.
 /// </summary>
 public bool Undefined(PredicateIndicator p)
 {
     if (PrologPrimitives.IsDefined(p))
     {
         return(false);
     }
     if (CheckForPredicateInfoInThisKB(p) != null)
     {
         return(false);
     }
     foreach (KnowledgeBase import in imports)
     {
         if (!import.Undefined(p))
         {
             return(false);
         }
     }
     return(true);
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Prints the byte code for the rule to System.Console.
        /// </summary>
        public void Disassemble()
        {
            ushort pc = 0;

            while (pc < code.Length)
            {
                var opcode = (Opcode)code[pc++];
                Console.Write("L{0}: {1} ", pc - 1, opcode.ToString());
                switch (opcode)
                {
                case Opcode.MatchStructure:
                {
                    Symbol functor    = GetSymbol(ref pc);
                    int    arity      = code[pc++];
                    int    endofMatch = GetUShort(ref pc);
                    Console.Write("{0}/{1}, L{2}, ", functor.Name, arity, endofMatch);
                    DisassembleOperand(ref pc);
                }
                break;

                case Opcode.MatchVar:
                case Opcode.MatchVarFirst:
                {
                    if (opcode == Opcode.MatchVarFirst)
                    {
                        Console.Write("{0}, ", GetSymbol(ref pc));
                    }
                    byte register = code[pc++];
                    Console.Write("{0}, ", FormatRegister(register));
                    DisassembleOperand(ref pc);
                }
                break;

                case Opcode.MatchLiteral:
                {
                    Console.Write(GetLiteral(ref pc));
                    Console.Write(", ");
                    DisassembleOperand(ref pc);
                }
                break;

                case Opcode.BuildStructure:
                {
                    Console.Write(GetSymbol(ref pc));
                    Console.Write("/{0}, ", code[pc++]);
                    DisassembleOperand(ref pc);
                }
                break;

                case Opcode.BuildVar:
                {
                    Console.Write(GetSymbol(ref pc));
                    Console.Write(", ");
                    DisassembleOperand(ref pc);
                }
                break;

                case Opcode.BuildReg:
                {
                    byte reg = code[pc++];
                    Console.Write("{0}, ", FormatRegister(reg));
                    DisassembleOperand(ref pc);
                }
                break;

                case Opcode.BuildLiteral:
                {
                    Console.Write(GetLiteral(ref pc));
                    DisassembleOperand(ref pc);
                }
                break;

                case Opcode.Call:
                case Opcode.CallPrimitive:
                case Opcode.CallWokenGoals:
                {
                    Console.Write("{0}", FormatRegister(code[pc++]));
                    Console.Write(", {0}", FormatLabel(GetUShort(ref pc)));
                    Console.Write(", {0}", FormatLabel(GetUShort(ref pc)));
                    if (opcode != Opcode.CallWokenGoals)
                    {
                        int arity;
                        if (opcode == Opcode.Call)
                        {
                            PredicateInfo p = GetPredicate(ref pc);
                            Console.Write(", {0}/{1}", p.Name, p.Arity);
                            arity = p.Arity;
                        }
                        else
                        {
                            PrologPrimitives.PrimitiveImplementation impl = GetPrimitive(ref pc);
                            arity = code[pc++];
                            Console.Write(", {0}/{1}", PrologPrimitives.PrimitiveName(impl), arity);
                        }
                        while (arity-- > 0)
                        {
                            Console.Write(", ");
                            int arg = code[pc++];
                            if (arg < 0x80)
                            {
                                Console.Write("{0}", FormatRegister(arg));         // It's a register
                            }
                            else
                            {
                                // It's a literal
                                arg = ((arg & 0x7f) << 8) + code[pc++];
                                Console.Write(GlobalLiteralTable[arg]);
                            }
                        }
                    }
                }
                break;

                default:
                    throw new Exception("Unknown opcode " + opcode);
                }
                Console.WriteLine();
            }
        }
Ejemplo n.º 7
0
 static KnowledgeBase()
 {
     Global = new KnowledgeBase("global", null, null);
     PrologPrimitives.InstallPrimitives();
 }
Ejemplo n.º 8
0
        private void WalkGoal(KnowledgeBase kb, KnowledgeBaseRule rule, Structure goal)
        {
            var    predicateIndicator = goal.PredicateIndicator;
            Symbol functor            = goal.Functor;
            int    arity = goal.Arity;

            switch (functor.Name)
            {
            case "begin":
                foreach (var arg in goal.Arguments)
                {
                    WalkGoal(kb, rule, arg);
                }
                break;

            case "once":
            case "check":
            case "randomize":
            case "not":
            case "\\+":
                if (arity == 1)
                {
                    WalkGoal(kb, rule, goal.Argument(0));
                }
                else
                {
                    WarnUndefined(rule, functor, arity);
                }
                break;

            case ",":
            case ";":
            case "->":
                if (arity == 2)
                {
                    WalkGoal(kb, rule, goal.Argument(0));
                    WalkGoal(kb, rule, goal.Argument(1));
                }
                else
                {
                    WarnUndefined(rule, functor, arity);
                }
                break;

            case "call":
            case "maplist":
                if (arity < 1)
                {
                    WarnUndefined(rule, functor, arity);
                }
                else
                {
                    object goalToCall            = goal.Argument(0);
                    var    goalToCallAsStructure = goalToCall as Structure;
                    if (goalToCallAsStructure != null)
                    {
                        var newArgs = new object[arity - 1 + goalToCallAsStructure.Arity];
                        goalToCallAsStructure.Arguments.CopyTo(newArgs, 0);
                        WalkGoal(kb, rule, new Structure(goalToCallAsStructure.Functor, newArgs));
                    }
                    else
                    {
                        var call = goalToCall as Symbol;
                        if (call != null)
                        {
                            this.WalkGoal(kb, rule, new Structure(call, new object[arity - 1]));
                        }
                    }
                }
                break;

            case "arg_min":
            case "arg_max":
                if (arity == 3)
                {
                    WalkGoal(kb, rule, goal.Argument(2));
                }
                else
                {
                    WarnUndefined(rule, functor, arity);
                }
                break;

            case "find_all":
                if (arity == 3)
                {
                    WalkGoal(kb, rule, goal.Argument(1));
                }
                else
                {
                    WarnUndefined(rule, functor, arity);
                }
                break;

            default:
                if (PrologPrimitives.IsDefined(predicateIndicator))
                {
                    var arglist = PrologPrimitives.Arglist(predicateIndicator.Functor);
                    for (int i = 0; i < Math.Min(predicateIndicator.Arity, arglist.Count); i++)
                    {
                        var argSym = arglist[i] as Symbol;
                        if (argSym != null)
                        {
                            var arg = argSym.Name;
                            if (arg[0] == ':')
                            {
                                WalkGoal(kb, rule, goal.Argument(i));
                            }
                            else if (arg == "..." && arglist[i - 1] is string && ((string)arglist[i - 1])[0] == ':')
                            {
                                // Predicate accepts a rest arg of goals
                                for (int j = i; j < predicateIndicator.Arity; j++)
                                {
                                    WalkGoal(kb, rule, goal.Argument(j));
                                }
                            }
                        }
                    }
                }
                else
                {
                    var predicate = kb.CheckForPredicateInfo(predicateIndicator);
                    if (predicate == null)
                    {
                        WarnUndefined(rule, functor, arity);
                    }
                    else
                    {
                        MarkReferenced(predicate);
                        if (predicate.HigherOrderArguments != null)
                        {
                            foreach (int argIndex in predicate.HigherOrderArguments)
                            {
                                WalkGoal(kb, rule, goal.Argument(argIndex));
                            }
                        }
                    }
                }
                break;
            }
        }