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); }
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); }
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)); }
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(']'); }
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))); }
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); }
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)); }
/// <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]))); }
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; }
/// <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); } }
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; } }