/// <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> /// Testing jig for byte compiler /// </summary> public void Test(string call) { var term = (Structure)(new ISOPrologReader(call).ReadTerm()); if (term.Arity != predicate.Arity) { throw new Exception("Wrong number of arguments"); } using (var c = PrologContext.Allocate(KnowledgeBase.Global, null)) { c.PushArguments(term.Arguments); int solutions = 0; foreach (var x in StackCall(c)) { foreach (var arg in term.Arguments) { if (arg is LogicVariable) { var l = arg as LogicVariable; Console.WriteLine("{0}={1}", l.Name, ISOPrologWriter.WriteToString(l.Value)); } } Console.WriteLine(x); if (solutions++ > 10) { Console.WriteLine("Max solutions found; terminating search"); c.PopFrame(0); goto abort; } } Console.WriteLine("fail"); abort: int tos = c.MakeFrame(0); if (tos != 0) { Console.WriteLine("Error: tos is " + tos); } } }
/// <summary> /// Attempts to prove the specified goal. /// WARNING: THIS WILL LEAK A PROLOG CONTEXT UNLESS ENUMERATED TO COMPLETION. /// </summary> internal IEnumerable<bool> Prove(Structure t) { using (var prologContext = PrologContext.Allocate(this, null)) { var enumerator = Prove(t.Functor, t.Arguments, prologContext, 0).GetEnumerator(); bool done = false; while (!done) { try { done = !enumerator.MoveNext() || enumerator.Current == CutState.ForceFail; } catch { PrologContext.LastExceptionContext = prologContext; throw; } if (!done) yield return false; } } }
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)); } } }