Esempio n. 1
0
        public static bool TryQueryStructure(
            Structure term,
            PrologContext context,
            out ELNode foundNode,
            out ELNodeEnumerator enumerator)
        {
            //
            // Dispatch based on the functor and arity.
            //

            // Handle root queries, i.e. /Key
            if (term.IsFunctor(Symbol.Slash, 1))
                return TryRootQuery(term, context, out foundNode, out enumerator);

            if (!IsELTerm(term))
                throw new Exception("Malformed EL query: " + ISOPrologWriter.WriteToString(term));

            if (term.IsFunctor(SBindNodeOperator, 2))
            {
                var variableToBind = term.Argument(1) as LogicVariable;
                if (variableToBind == null)
                    throw new ArgumentException("RHS of >> must be an uninstantiated variable: "+ ISOPrologWriter.WriteToString(term.Argument(1)));
                foundNode = null;
                return TryNodeBindingQuery(out enumerator, term.Argument(0), variableToBind, context);
            }

            return TryChildQuery(
                out foundNode,
                out enumerator,
                term.Argument(0),
                term.Argument(1),
                term.Functor == Symbol.Colon,
                context);
        }
Esempio n. 2
0
 internal IEnumerable<CutState> Retract(object term)
 {
     Structure head = Term.Structurify(term, "Argument to retract must be a valid term.");
     object body = Symbol.True;
     if (head.IsFunctor(Symbol.Implication, 2))
     {
         body = head.Argument(1);
         head = Term.Structurify(head.Argument(0), "Invalid clause head.");
     }
     return Retract(head, body);
 }
Esempio n. 3
0
 public static ELNode UpdateStructure(Structure term, KnowledgeBase knowledgeBase)
 {
     if (term.Functor == Symbol.Slash)
     {
         if (term.Arity == 1)
             return knowledgeBase.ELRoot.StoreNonExclusive(Term.CopyInstantiation(term.Argument(0)));
         return Update(term.Argument(0), knowledgeBase).StoreNonExclusive(Term.CopyInstantiation(term.Argument(1)));
     }
     if (term.Functor == Symbol.Colon)
     {
         return Update(term.Argument(0), knowledgeBase).StoreExclusive(Term.CopyInstantiation(term.Argument(1)), true); 
     }
     throw new Exception("Malformed EL assertion: "+ISOPrologWriter.WriteToString(term));
 }
Esempio n. 4
0
        private void WritePrologList(StringBuilder s)
        {
            s.Append('[');
            bool          first   = true;
            object        current = Canonicalize(this);
            LogicVariable l       = current as LogicVariable;

            if (l != null && l.IsBound)
            {
                current = l.Value;
            }
            while (current != null)
            {
                Structure t = current as Structure;

                if (first)
                {
                    first = false;
                }
                else if (t == null)
                {
                    s.Append(" | ");
                }
                else
                {
                    s.Append(", ");
                }
                if (t == null)
                {
                    Write(s, current);
                    current = null;
                }
                else
                {
                    if (t.IsFunctor(Symbol.PrologListConstructor, 2))
                    {
                        Write(s, t.Argument(0));
                        current = t.Argument(1);
                    }
                    else
                    {
                        WriteAndPossiblyParenthesize(s, current);
                        current = null;
                    }
                }
            }
            s.Append(']');
        }
Esempio n. 5
0
        private static Structure ExpandDCGLiteral(Structure literal, object afterward, LogicVariable start, out LogicVariable rest)
        {
            if (literal == null)
            {
                return(ExpandDCGRuleBody(afterward, start, out rest));
            }
            if (literal.Argument(1) == null && afterward == null)
            {
                rest = new LogicVariable(RestSym);
                return(new Structure(DefiniteClauseCapitalC, start, literal.Argument(0), rest));
            }
            var intermediate = new LogicVariable(LSym);

            return(new Structure(Symbol.Comma,
                                 new Structure(DefiniteClauseCapitalC, start, literal.Argument(0), intermediate),
                                 ExpandDCGLiteral((Structure)literal.Argument(1), afterward, intermediate, out rest)));
        }
Esempio n. 6
0
        private static bool TryRootQuery(Structure term, PrologContext context, out ELNode foundNode, out ELNodeEnumerator enumerator)
        {
            // Expression is /Key.
            var arg0 = term.Argument(0);

            // This is a "/constant" expression, i.e. a top-level lookup.
            if (arg0 is LogicVariable)
            {
                throw new NotImplementedException("Lookups of the form /Variable are not supported.");
            }
            enumerator = null;
            return context.KnowledgeBase.ELRoot.TryLookup(arg0, out foundNode);
        }
Esempio n. 7
0
            private void CompileMatcher(byte register, byte argument, object obj)
            {
                obj = Term.Deref(obj);
                var lv = obj as LogicVariable;

                if (lv != null)
                {
                    var info = env[lv];
                    if (register != NoRegister || info.register != argument)   // If top level and first occurance, don't bother.
                    {
                        env.InsureAllocated(info);
                        if (info.AlreadyStored)
                        {
                            Emit(Opcode.MatchVar, info.register);
                        }
                        else
                        {
                            Emit(Opcode.MatchVarFirst, SymbolTable.IndexOf(lv.Name), info.register);
                        }
                        EmitOperand(register, argument);
                    }
                    env.OneUseCompiled(info);
                }
                else
                {
                    var structure = obj as Structure;
                    if (structure != null)
                    {
                        Structure s = structure;
                        byte      destinationRegister = (register == NoRegister)?argument:this.env.GetRegister();
                        this.Emit(Opcode.MatchStructure, SymbolTable.IndexOf(s.Functor), (byte)s.Arity);
                        ushort backPatchAddress = this.CurrentPC;
                        this.EmitUShort(0);
                        this.EmitOperand(register, argument, destinationRegister);
                        for (byte i = 0; i < s.Arity; i++)
                        {
                            this.CompileMatcher(destinationRegister, i, s.Argument(i));
                        }
                        this.BackPatch(backPatchAddress, this.CurrentPC);
                        if (register != NoRegister)
                        {
                            this.env.FreeRegister(destinationRegister);
                        }
                    }
                    else
                    {
                        this.Emit(Opcode.MatchLiteral, GlobalLiteralTable.IndexOf(obj));
                        this.EmitOperand(register, argument);
                    }
                }
            }
 /// <summary>
 /// Creates a KnowledgedBaseRule given a Term object for a :- expression.
 /// </summary>
 public static KnowledgeBaseRule FromTerm(Structure structure, bool checkSingletons, string source, int line)
 {
     if (structure == null)
     {
         throw new ArgumentNullException("structure");
     }
     if (structure.IsFunctor(Symbol.Implication, 2))
     {
         var body = new List <Structure>();
         UnwindCommaExpression(structure.Argument(1), body);
         if (structure.Argument(0) == null)
         {
             throw new ArgumentException("head of rule is null");
         }
         Structure head = Term.Structurify(structure.Argument(0), "Head of :- must be a valid proposition or predicate.");
         if (head == null)
         {
             throw new ArgumentException("Head of rule is not a term.");
         }
         return(MakeRule(head, body, checkSingletons, source, line));
     }
     return(MakeRule(structure, null, checkSingletons, source, line));
 }
Esempio n. 9
0
        /// <summary>
        /// Returns the Term whose functor is the first element of the list and whose arguments are the other elements of the list.
        /// Functional version of =..
        /// </summary>
        public static Structure FromList(Structure listExpression)
        {
            if (listExpression == null || !listExpression.IsFunctor(Symbol.PrologListConstructor, 2))
            {
                throw new ArgumentException("Argument must be a prolog list");
            }
            object functorArg = listExpression.Argument(0);

            if (functorArg == null)
            {
                throw new ArgumentException("First element of list (functor) must be a symbol.");
            }
            var functor = functorArg as Symbol;

            if (functor == null)
            {
                throw new ArgumentException("First element of list (functor) must be a symbol.");
            }
            return(new Structure(functor, Prolog.PrologListToArray(listExpression.Arguments[1])));
        }
Esempio n. 10
0
            private void CompileGoal(Structure goal, ref ushort failAddress, ref ushort backPatchAddress)
            {
                byte continuationRegister = env.GetRegister();
                // Allocate registers to goal arguments.
                var argRegisters = new byte[goal.Arity];

                for (int i = 0; i < goal.Arity; i++)
                {
                    object arg = goal.Argument(i);
                    if (arg is Structure)
                    {
                        argRegisters[i] = env.GetRegister();
                    }
                    else
                    {
                        var @var = arg as LogicVariable;
                        if (@var != null)
                        {
                            argRegisters[i] = this.env.InsureRegisterAndLock(@var);
                        }
                        else
                        {
                            // It's a literal.
                            argRegisters[i] = NoRegister;
                        }
                    }
                }

                // Build goal arguments into registers.
                for (int i = 0; i < goal.Arity; i++)
                {
                    if (argRegisters[i] != NoRegister)
                    {
                        CompileBuild(goal.Argument(i), NoRegister, argRegisters[i]);
                    }
                }

                // Emit call instruction
                ushort startOfCallInstruction = CurrentPC;

                BackPatch(backPatchAddress, startOfCallInstruction);
                PrologPrimitives.PrimitiveImplementation primitiveImplementation;
                bool isPrimitive = PrologPrimitives.Implementations.TryGetValue(goal.Functor,
                                                                                out primitiveImplementation);

                // Call header
                Emit(isPrimitive?Opcode.CallPrimitive : Opcode.Call, continuationRegister);
                EmitUShort(failAddress);
                backPatchAddress = CurrentPC;
                EmitUShort(0);      // This will get backpatched
                // Call target
                if (isPrimitive)
                {
                    EmitUShort(PrimitiveTable.IndexOf(primitiveImplementation));
                    EmitByte((byte)goal.Arity);
                }
                else
                {
                    EmitUShort(PredicateTable.IndexOf(this.knowledgeBase.EntryForStoring(goal.PredicateIndicator)));
                }
                // Call arguments
                for (int i = 0; i < goal.Arity; i++)
                {
                    byte reg = argRegisters[i];
                    if (reg == NoRegister)
                    {
                        EmitUShort((ushort)(0x8000 + GlobalLiteralTable.IndexOf(goal.Argument(i))));
                    }
                    else
                    {
                        EmitByte(reg);
                    }
                }
                failAddress = startOfCallInstruction;
            }
Esempio n. 11
0
        /// <summary>
        /// Add a term (fact or rule) to the KB.
        /// </summary>
        public void Assert(Structure structure, bool atEnd, bool checkSingletons)
        {
            if (structure == null)
            {
                throw new ArgumentNullException("structure", "Term to add to KB may not be null.");
            }
            //structure = structure.Expand();

            if (structure == null)
            {
                throw new ArgumentNullException("structure");
            }

            Structure head = structure.IsFunctor(Symbol.Implication, 2)
                                 ? Term.Structurify(structure.Argument(0),
                                                    "Head of :- must be a valid proposition or predicate.")
                                 : structure;

            if (head.IsFunctor(Symbol.ColonColon, 2))
            {
                var argument = head.Argument(0);
                var kb       = argument as KnowledgeBase;
                if (kb == null)
                {
                    var o = argument as GameObject;
                    if (o != null)
                    {
                        kb = o.KnowledgeBase();
                    }
                    else
                    {
                        var c = argument as Component;
                        if (c != null)
                        {
                            kb = c.KnowledgeBase();
                        }
                        else
                        {
                            throw new ArgumentTypeException(
                                      "assert",
                                      "knowledgebase",
                                      argument,
                                      typeof(KnowledgeBase));
                        }
                    }
                }
                if (structure.IsFunctor(Symbol.Implication, 2))
                {
                    kb.Assert(
                        new Structure(Symbol.Implication, head.Argument(1), structure.Argument(1)),
                        atEnd,
                        checkSingletons);
                }
                else
                {
                    kb.Assert(structure.Argument(1), atEnd, checkSingletons);
                }
            }
            else
            {
                if (PrologPrimitives.Implementations.ContainsKey(head.Functor))
                {
                    throw new PrologException(
                              new Structure(
                                  "error",
                                  new Structure(
                                      "permission_error",
                                      Symbol.Intern("modify"),
                                      Symbol.Intern("static_procedure"),
                                      Term.PredicateIndicatorExpression(head))));
                }

                KnowledgeBaseRule assertion = KnowledgeBaseRule.FromTerm(
                    structure,
                    checkSingletons,
                    Prolog.CurrentSourceFile,
                    Prolog.CurrentSourceLineNumber);
                PredicateInfo info = EntryForStoring(head.PredicateIndicator);
                PredicateInfo parentInfo;
                if (!info.Shadow && this.Parent != null &&
                    (parentInfo = this.Parent.CheckForPredicateInfoInThisKB(head.PredicateIndicator)) != null &&
                    !parentInfo.External)
                {
                    throw new PrologException(
                              new Structure(
                                  "error",
                                  new Structure(
                                      "permission_error",
                                      Symbol.Intern("shadow"),
                                      Term.PredicateIndicatorExpression(head))));
                }

                info.Assert(assertion, atEnd);
            }
        }
Esempio n. 12
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;
            }
        }