static private Structurify ( object term, string errorMessage ) : Structure | ||
term | object | |
errorMessage | string | |
return | Structure |
internal static void UnwindCommaExpression(object subgoal, List <Structure> body) { if (subgoal == null) { throw new ArgumentNullException("subgoal", "Subgoal of rule is null"); } Structure structure; if (subgoal is LogicVariable) { structure = new Structure(Symbol.Call, subgoal); } else { structure = Term.Structurify(subgoal, "Not a valid subgoal."); } if (structure.IsFunctor(Symbol.Comma, 2)) { UnwindCommaExpression(structure.Argument(0), body); UnwindCommaExpression(structure.Argument(1), body); } else { body.Add(structure); } }
private void StartNewQuery(string command) { try { foundOneSolution = false; PrologContext.Reset(CurrentGameObject); PrologContext.Output = Output; PrologContext.PushGoalStack(Symbol.Intern("parse"), new object[] { command }, 0); object query = ISOPrologReader.ReadAndGetFreeVariables(command, freeVariablesInCurrentQuery); if (query == null) { throw new ArgumentNullException("command", "Prolog query may not be null."); } var goal = Term.Structurify(query, "Not a valid Prolog goal."); if (goal.IsFunctor(Symbol.PrologListConstructor, 2) && goal.Argument(1) == null) { goal = new Structure("reconsult", goal.Argument(0)); } prologModeAnswerStream = PrologContext.ResetStackAndProve(goal).GetEnumerator(); PrintNextQuerySolution(); } catch (Exception) { StartErrorReport(); prologModeAnswerStream = null; if (PrologContext.GoalStackDepth > 0) { Output.WriteLine("In goal: {0}", PrologContext.GoalStackTop); } throw; } }
/// <summary> /// True if the specified goal is provable within this KnowledgeBase. /// </summary> /// <param name="goal">Goal to attempt to prove</param> /// <param name="thisValue">The value to give ot the $this indexical while running the goal</param> /// <returns>Success</returns> public bool IsTrue(object goal, object thisValue = null) { var t = Term.Structurify(goal, "Argument to IsTrue() should be a valid Prolog goal."); bool result; using (var prologContext = PrologContext.Allocate(this, thisValue)) { try { result = Prove(t.Functor, t.Arguments, prologContext, 0).GetEnumerator().MoveNext(); } catch (InferenceStepsExceededException) { throw; } catch (Exception e) { throw new PrologError( e, prologContext.StackTrace( Prolog.CurrentSourceFile, Prolog.CurrentSourceLineNumber, "IsTrue()", false) + e.StackTrace); } } return(result); }
/// <summary> /// Remove a term from the KB. /// </summary> public void RetractAll(object term) { if (term == null) { throw new ArgumentNullException("term", "Term to retract cannot be null."); } RetractAll(Term.Structurify(term, "Fact is not a valid proposition or predicate.")); }
/// <summary> /// True if the specified goal is provable within this KnowledgeBase. /// </summary> /// <param name="result">Value of variable to return</param> /// <param name="goal">Goal to attempt to prove</param> /// <param name="throwOnFailure">If true, SolveFor will throw a GoalException if the goal fails</param> /// <param name="thisValue">Value to give ot the indexical $this during execution</param> /// <returns>Success</returns> public object SolveFor(LogicVariable result, object goal, object thisValue, bool throwOnFailure = true) { if (this.IsTrue(Term.Structurify(goal, "Argument to SolveFor() should be a valid Prolog goal."), thisValue)) return Term.CopyInstantiation(result); if (throwOnFailure) throw new GoalException(goal, "Goal is unsatisfiable"); return null; }
/// <summary> /// Byte compiles all the rules in this predicate. /// </summary> public void Compile() { for (int i = 0; i < Entries.Count; i++) { var entry = Entries[i] as KnowledgeBaseRule; if (entry != null && !(entry is ByteCompiledRule)) { Entries[i] = new ByteCompiledRule(this, Term.Structurify(entry.Head, "Malformed head."), entry.BodyGoals, entry.SourceFile, entry.SourceLineNumber); } } }
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); }
/// <summary> /// Add a term (fact or rule) to the KB. /// </summary> public void Assert(object term, bool atEnd, bool checkSingletons) { if (term == null) throw new ArgumentNullException("term", "Term to assert in KB cannot be null."); if (ELProlog.IsELTerm(term)) ELProlog.Update(term, this); else { Assert( Term.Structurify(term, "Assertion is not a valid proposition or predicate."), atEnd, checkSingletons); } }
/// <summary> /// Resets the context (clears stack, etc.) and starts a proof of the specified goal. /// </summary> /// <param name="goal">Goal to attempt to prove</param> /// <returns>Enumerator for solutions</returns> public IEnumerable <bool> ResetStackAndProve(object goal) { Reset(this.This); Structure s = Term.Structurify(goal, "Invalid goal."); foreach (var state in KnowledgeBase.Prove(s.Functor, s.Arguments, this, 0)) { if (state == CutState.ForceFail) { yield break; } else { yield return(false); } } }
/// <summary> /// For testing purposes /// </summary> /// <param name="code"></param> /// <returns></returns> public static ByteCompiledRule FromCode(string code) { var term = (Structure)(new ISOPrologReader(code).ReadTerm()); Structure head; Structure[] body; if (term.IsFunctor(Symbol.Intern(":-"), 2)) { head = Term.Structurify(term.Argument(0), "Bad rule head."); var bodyList = new List <Structure>(); UnwindCommaExpression(term.Argument(1), bodyList); body = bodyList.ToArray(); } else { head = Term.Structurify(term, "Bad rule head"); body = new Structure[0]; } return(new ByteCompiledRule(KnowledgeBase.Global.EntryForStoring(head.PredicateIndicator), head, body, "none", 1)); }
/// <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> /// Proves the specified goal, throwing an exception with badGoalErrorMessage if the goal is ill-formed. /// </summary> internal IEnumerable <CutState> Prove(object goal, string badGoalErrorMessage) { Structure s = Term.Structurify(goal, badGoalErrorMessage); return(KnowledgeBase.Prove(s.Functor, s.Arguments, this, CurrentFrame)); }
public void Consult(TextReader inStream) { sourceFiles.NoteFile(Prolog.CurrentSourceFile); var reader = new ISOPrologReader(inStream); reader.SkipLayout(); int lastLine = reader.LineNumber; using (var context = PrologContext.Allocate(this, this)) { try { object unexpanded; Prolog.CurrentSourceLineNumber = lastLine; while ((unexpanded = reader.ReadTerm()) != Symbol.EndOfFile) { // Perform user-level macroexpansion. object assertion = TermExpansion(unexpanded); if (ELProlog.IsELTerm(assertion)) { // It's an EL term. ELProlog.Update(assertion, this); } else { // It's a normal Prolog term var t = Term.Structurify( assertion, "Assertions in prolog files must be valid propositions or predicates."); // Perform built-in macroexpansion. t = t.Expand(); if (t.IsFunctor(Symbol.Implication, 1)) { context.Reset(); var goal = Term.Structurify( t.Argument(0), "Argument to a :- directive must be an atom or structure."); // Run t once, but don't backtrack for a second solution (since it's presumably an imperative anyway). Prove(goal.Functor, goal.Arguments, context, 0).GetEnumerator().MoveNext(); } else { Assert(t, true, true); } } reader.SkipLayout(); lastLine = reader.LineNumber; Prolog.CurrentSourceLineNumber = lastLine; } } catch (InferenceStepsExceededException e) { Repl.RecordExceptionSourceLocation(e, lastLine); throw; } catch (Exception e) { UnityEngine.Debug.LogException(e); Repl.RecordExceptionSourceLocation(e, lastLine); throw new PrologError( e, context.StackTrace(Prolog.CurrentSourceFile, Prolog.CurrentSourceLineNumber, "consult/1", false)); } } }
/// <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); } }