public static bool Unify(object v1, object v2, PrologContext context) { object o1 = Deref(v1); object o2 = Deref(v2); if (o1 == o2) { // Fast path return(true); } var t1 = o1 as Term; var t2 = o2 as Term; if (t1 != null) { if (t2 != null) { return(t1.UnifyWithTerm(t2, context)); } return(t1.UnifyWithAtomicConstant(o2, context)); } // o1 isn't a Term if (t2 != null) { // o2 is a Term return(t2.UnifyWithAtomicConstant(o1, context)); } // Neither is a Term if (o1 == null) { return(o2 == null); } return(o1.Equals(o2)); }
internal static IEnumerable<CutState> SetImplementation(object[] args, PrologContext context) { if (args.Length != 2) throw new ArgumentCountException("set", args, new object[] { "Variable", "NewValue"}); object value = Term.CopyInstantiation(args[1]); if (value is LogicVariable) throw new UninstantiatedVariableException((LogicVariable)args[1], "Value argument should be a data object, not an uninstantiated (unbound) variable."); var functor = Term.Deref(args[0]) as Symbol; if (functor == null) throw new ArgumentTypeException("set", "functor", args[0], typeof (Symbol)); List<KnowledgeBaseEntry> entries = context.KnowledgeBase.EntryListForStoring(new PredicateIndicator(functor, 1)); switch (entries.Count) { case 0: entries.Add(new KnowledgeBaseVariable(value)); return CutStateSequencer.Succeed(); case 1: var v = entries[0] as KnowledgeBaseVariable; if (v==null) throw new ArgumentException("Functor is not a variable; it has another entry defined for it."); v.CurrentValue = value; return CutStateSequencer.Succeed(); default: throw new ArgumentException("Functor is not a variable; it has multiple entries defined for it."); } }
public static bool TryChildQuery( out ELNode foundNode, out ELNodeEnumerator enumerator, object parentExpression, object keyExpression, bool isExclusive, PrologContext context) { // Decode the parent expression ELNode parentNode; ELNodeEnumerator parentEnumerator; if (!TryQuery(parentExpression, context, out parentNode, out parentEnumerator)) { // Parent failed, so we fail enumerator = null; foundNode = null; return false; } // // Decode the key argument // var key = keyExpression; var v = key as LogicVariable; return isExclusive?TryExclusiveQuery(out foundNode, out enumerator, parentNode, parentEnumerator, key, v) : TryNonExclusiveQuery(out foundNode, out enumerator, parentNode, key, v, parentEnumerator); }
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); }
public static bool TryQuery(object term, PrologContext context, out ELNode foundNode, out ELNodeEnumerator enumerator) { // Dereference any top-level variables. var t = Term.Deref(term); // Dereference indexicals var i = t as Indexical; if (i != null) t = i.GetValue(context); // A game object means the gameobject's EL KB. var g = t as GameObject; if (g != null) t = g.KnowledgeBase().ELRoot; // If it's already an ELNode, use that. var n = t as ELNode; if (n != null) { foundNode = n; enumerator = null; return true; } // Otherwise, it's an expression, so evaluate it. var s = t as Structure; if (s != null) return TryQueryStructure(s, context, out foundNode, out enumerator); var v = t as LogicVariable; if (v != null && !v.IsBound) throw new Exception("EL query root is an unbound variable: " + v); throw new Exception("Malformed EL query: " + ISOPrologWriter.WriteToString(term)); }
private void DumpPrologStack(PrologContext context) { if (context.GoalStackDepth > 0) { for (ushort i = 0; i <= context.CurrentFrame; i++) { Structure g = context.GoalStackGoal(i); if (g != null) { ushort frame = i; while (frame != 0) { //Output.Write("{0}/", frame); Output.Write(" "); frame = context.GoalStackParent(frame); } //Output.Write(' '); //Output.Write("{0}<{1}: ", i, PrologContext.GoalStackParent(i)); Output.WriteLine(Term.ToStringInPrologFormat(g)); } } } else { Output.WriteLine("Goal stack is empty."); } }
/// <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); }
internal override IEnumerable <CutState> Prove(object[] args, PrologContext context, ushort parentFrame) { object[] goal1Args = null; var newVars = new LogicVariable[FreeVariables.Count]; object[] newArgs = Term.AlphaConvertArglist(HeadArgs, FreeVariables, newVars, context, true); // ReSharper disable UnusedVariable #pragma warning disable 414, 168, 219 foreach (bool ignore in Term.UnifyArraysFast(args, newArgs, context)) #pragma warning restore 414, 168, 219 { if (goal1Args == null) { goal1Args = Term.AlphaConvertArglist(BodyGoals[0].Arguments, FreeVariables, newVars, context, false); } #pragma warning disable 414, 168, 219 foreach (CutState ignoreFreeze in context.ProveAllWokenGoals()) #pragma warning restore 414, 168, 219 { // ReSharper restore UnusedVariable foreach (CutState state1 in context.KnowledgeBase.Prove(BodyGoals[0].Functor, goal1Args, context, parentFrame)) { yield return(state1); } } } }
internal override Metastructure MetaVarUnify(LogicVariable l, PrologContext context) { if (DelayedGoal != null) { context.WakeUpGoal(DelayedGoal); } return(MakeSuspension(null, FrozenGoal)); }
internal override bool UnifyWithStructure(Structure value, PrologContext context) { if (value == null || value.Functor != Functor || value.Arguments.Length != Arguments.Length) { return(false); } return(UnifyArrays(Arguments, value.Arguments, context)); }
internal override IEnumerable <CutState> Prove(object[] args, PrologContext context, ushort parentFrame) { if (args.Length != 1) { throw new ArgumentCountException("variable", args, new object[] { "Value" }); } return(Term.UnifyAndReturnCutState(CurrentValue, args[0])); }
internal IEnumerable <CutState> StackCall(PrologContext context) { if (Compiled) { return(TestCompiledClauses(context)); } return(Prove(context.GetCallArgumentsAsArray(Arity), context)); }
internal override Metastructure MetaMetaUnify(Metastructure theirMetaStructure, PrologContext context) { var s = theirMetaStructure as Suspension; if (s == null) throw new ArgumentTypeException("MetaMetaUnify", "theirMetaStructure", theirMetaStructure, typeof(Suspension)); if (context != s.context) throw new ArgumentException("Can't unify suspended goals across PrologContexts."); context.WakeUpGoal(CombineGoals(DelayedGoal, s.DelayedGoal)); return MakeSuspension(null, CombineGoals(FrozenGoal, s.FrozenGoal)); }
internal static IEnumerable <bool> UnifyArraysFast(object[] a1, object[] a2, PrologContext context) { int mark = context.MarkTrail(); if (UnifyArrays(a1, a2, context)) { yield return(false); } context.RestoreVariables(mark); }
internal static void RetractAll(object term, PrologContext context) { ELNode foundNode; ELNodeEnumerator enumerator; if (!TryQuery(term, context, out foundNode, out enumerator)) return; if (foundNode != null) foundNode.DeleteSelf(); else while (enumerator.MoveNext()) enumerator.Current.DeleteSelf(); }
/// <summary> /// Attempts to prove the specified goal. /// </summary> internal IEnumerable <CutState> Prove(Symbol functor, object[] args, PrologContext context, ushort parentFrame) { context.PushGoalStack(functor, args, parentFrame); context.NewStep(); PrologPrimitives.PrimitiveImplementation prim; if (PrologPrimitives.Implementations.TryGetValue(functor, out prim)) { return(CallPrimitive(functor, prim, args, context)); } return(ProveFromDB(functor, args, context)); }
public static IEnumerable <CutState> SucceedAndRestoreTrail(PrologContext context, int trailMark) { try { yield return(CutState.Continue); } finally { context.RestoreVariables(trailMark); } }
private void PushCallArgs(PrologContext context, int framePointer, int arity, ref ushort pc) { for (int i = 0; i < arity; i++) { byte maybeReg = code[pc++]; object argumentValue = (maybeReg < 0x80) ? context.GetStack(framePointer, maybeReg & 0x7f) : GlobalLiteralTable[((maybeReg & 0x7f) << 8) + code[pc++]]; context.SetCallArg(i, argumentValue); } }
// ReSharper disable once InconsistentNaming IEnumerable<CutState> ProveFromDB(Symbol functor, object[] args, PrologContext context) { PredicateInfo info = GetPredicateInfo(this, new PredicateIndicator(functor, args.Length)); if (info == null) { if (ErrorOnUndefined) throw new UndefinedPredicateException(functor, args.Length); return PrologPrimitives.FailImplementation; } return info.Prove(args, context); }
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); }
/// <summary> /// Merge the information from two Metastructures into one new metastructure. /// </summary> /// <param name="theirMetaStructure">The Metastructure to merge with.</param> /// <param name="context">Context in which to execute suspended goals.</param> /// <returns>The merged Metastructure.</returns> public Metastructure MetaMetaUnify(Metastructure theirMetaStructure, PrologContext context) { if (theirMetaStructure == null) { throw new ArgumentTypeException("MetaMetaUnify", "theirMetaStructure", theirMetaStructure, typeof(Metastructure)); } if (context != theirMetaStructure.Context) { throw new ArgumentException("Can't unify suspended goals across PrologContexts."); } context.WakeUpGoal(CombineGoals(DelayedGoal, theirMetaStructure.DelayedGoal)); return(MakeSuspension(null, CombineGoals(FrozenGoal, theirMetaStructure.FrozenGoal))); }
internal IEnumerable <CutState> AddSuspendedGoal(Structure goal, PrologContext context) { var old = MetaBinding; mValue = new Metastructure(goal, null, context, old); try { yield return(CutState.Continue); } finally { mValue = (object)old ?? this; } }
internal IEnumerable <CutState> AddFrozenGoal(Structure goal, PrologContext context) { var old = MetaBinding; mValue = new Metastructure(null, goal, context, old); try { yield return(CutState.Continue); } finally { mValue = old; } }
internal override IEnumerable <CutState> Prove(object[] args, PrologContext context, ushort parentFrame) { var newVars = new LogicVariable[FreeVariables.Count]; object[] newArgs = Term.AlphaConvertArglist(HeadArgs, FreeVariables, newVars, context, true); // ReSharper disable UnusedVariable #pragma warning disable 414, 168, 219 foreach (bool ignore in Term.UnifyArrays(args, newArgs)) #pragma warning restore 414, 168, 219 { // ReSharper restore UnusedVariable yield return(CutState.Continue); } }
#pragma warning disable 414, 168, 219 /// <summary> /// Unifies arrays using trailing /// </summary> /// <returns>Success</returns> internal static bool UnifyArrays(object[] a1, object[] a2, PrologContext context) { if (a1.Length != a2.Length) { return(false); } for (int i = 0; i < a1.Length; i++) { if (!Unify(a1[i], a2[i], context)) { return(false); } } return(true); }
internal static IEnumerable <CutState> Retract(object term, PrologContext context) { ELNode foundNode; ELNodeEnumerator enumerator; if (!TryQuery(term, context, out foundNode, out enumerator)) { return(CutStateSequencer.Fail()); } if (foundNode != null) { foundNode.DeleteSelf(); return(CutStateSequencer.Succeed()); } return(DeleteSuccessive(enumerator)); }
/// <summary> /// Tests clauses in a randomized order (but still exhaustively). /// Uses Shuffler to generate a random permutation. /// </summary> IEnumerable <CutState> TestShuffledClauses(object[] args, PrologContext context, ushort myFrame) { entriesListUsed = true; var mark = context.MarkTrace(); var shuffler = new Shuffler((ushort)Entries.Count); var argIndexers = PredicateArgumentIndexer.ArglistIndexers(args); while (!shuffler.Done) { var entry = Entries[shuffler.Next()]; if (entry.Prematch(argIndexers)) { // This shouldn't be here... //context.PushGoalStack(Name, args, myFrame); context.SetCurrentRule(entry); foreach (var cutState in entry.Prove(args, context, myFrame)) { if (cutState == CutState.ForceFail) { if (KnowledgeBase.Trace || Trace) { context.TraceOutput("Cut: {0}", new Structure(Name, args)); } goto fail; } if (KnowledgeBase.Trace || Trace) { context.TraceOutput("Succeed: {0}", new Structure(Name, args)); } yield return(CutState.Continue); if (KnowledgeBase.Trace || Trace) { context.TraceOutput("Retry: {0}", new Structure(Name, args)); } } } } fail: context.RestoreVariables(mark); if (KnowledgeBase.Trace || Trace) { context.TraceOutput("Fail: {0}", new Structure(Name, args)); } //context.UnwindStack(Name, args); context.UnwindStack(myFrame); }
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); }
private IEnumerable <CutState> TestCompiledClauses(PrologContext context) { foreach (var knowledgeBaseEntry in Entries) { var rule = (ByteCompiledRule)knowledgeBaseEntry; foreach (var result in rule.StackCall(context)) { if (result == CutState.ForceFail) { yield break; } else { yield return(result); } } } }
private object DecodeOperand(PrologContext context, int framePointer, ref ushort pc) { int registerNumber = code[pc++]; object value = Term.Deref(context.GetStack(framePointer, registerNumber & 0x7f)); if (registerNumber < 0x80) { return(value); } int argNumber = code[pc++]; value = ((Structure)value).Argument(argNumber & 0x7f); if (argNumber >= 0x80) { context.SetStack(framePointer, code[pc++], value); } return(value); }
internal bool UnifyWithCanonicalValue(object value, PrologContext context) { if (!IsBound) { Metastructure m = MetaBinding; if (m == null) { // We're binding a truly unbound variable to something. if (value != this) { var xl = value as LogicVariable; if (xl != null) { Metastructure xm2; if ((xm2 = xl.MetaBinding) != null) { // We're binding a truly unbound variable to a meta-bound variable xl.UnifyMetaVar(xm2, this, context); return(true); } } SaveAndUpdate(value, context); // sets IsBound } return(true); } // This is an attributed (metabound) variable var l = value as LogicVariable; if (l == null) { UnifyMetaTerm(m, value, context); return(true); } Metastructure m2 = l.MetaBinding; if (m2 == null) { // Need to alias l to this, that's most easily done by letting l unify to this. UnifyMetaVar(m, l, context); return(true); } UnifyMetaMeta(m, m2, l, context); return(true); } return(Value.Equals(value)); }
private void SetOperand(PrologContext context, int framePointer, ref ushort pc, object newValue) { int registerNumber = code[pc++]; if (registerNumber < 0x80) { context.SetStack(framePointer, registerNumber, newValue); } else { object s = Term.Deref(context.GetStack(framePointer, registerNumber & 0x7f)); int argNumber = code[pc++]; object value = ((Structure)s).Arguments[argNumber & 0x7f] = newValue; if (argNumber >= 0x80) { context.SetStack(framePointer, code[pc++], value); } } }
public static bool TryNodeBindingQuery( out ELNodeEnumerator enumerator, object nodeExpression, LogicVariable variableToBind, PrologContext context) { // Decode the node expression ELNode foundNode; ELNodeEnumerator nodeEnumerator; if (!TryQuery(nodeExpression, context, out foundNode, out nodeEnumerator)) { // Parent failed, so we fail enumerator = null; return false; } enumerator = (foundNode != null) ? (ELNodeEnumerator)new ELNodeEnumeratorBindFixedNodeToVariable(foundNode, variableToBind) : new ELNodeEnumeratorBindEnumeratedNodesToVariable(nodeEnumerator, variableToBind); return true; }
/// <summary> /// Merge the information from two Metastructures into one new metastructure. /// </summary> /// <param name="theirMetaStructure">The Metastructure to merge with.</param> /// <param name="context">Context in which to execute suspended goals.</param> /// <returns>The merged Metastructure.</returns> public Metastructure MetaMetaUnify(Metastructure theirMetaStructure, PrologContext context) { if (theirMetaStructure == null) throw new ArgumentTypeException("MetaMetaUnify", "theirMetaStructure", theirMetaStructure, typeof(Metastructure)); if (context != theirMetaStructure.Context) throw new ArgumentException("Can't unify suspended goals across PrologContexts."); context.WakeUpGoal(CombineGoals(DelayedGoal, theirMetaStructure.DelayedGoal)); return MakeSuspension(null, CombineGoals(FrozenGoal, theirMetaStructure.FrozenGoal)); }
private static IEnumerable<CutState> IfThenElseImplementation(object test, object consequent, object alternative, PrologContext context) { #pragma warning disable 414, 168, 219 // ReSharper disable UnusedVariable foreach (var ignore in context.Prove(test, "Arguments to -> must be valid subgoals.")) // ReSharper restore UnusedVariable { // ReSharper disable UnusedVariable foreach (var ignore2 in context.Prove(consequent, "Arguments to -> must be valid subgoals.")) // ReSharper restore UnusedVariable { yield return CutState.Continue; } yield break; } // ReSharper disable UnusedVariable foreach (var ignore in context.Prove(alternative, "Arguments to -> must be valid subgoals.")) // ReSharper restore UnusedVariable { yield return CutState.Continue; } #pragma warning restore 414, 168, 219 }
private static IEnumerable<CutState> RealOrImplementation(object[] args, PrologContext context) { foreach (var status1 in context.Prove(args[0], "Arguments to ; (or) must be valid subgoals.")) { if (status1 == CutState.ForceFail) { //yield return status1; yield break; } yield return CutState.Continue; } foreach (var status2 in context.Prove(args[1], "Arguments to ; (or) must be valid subgoals.")) { if (status2 == CutState.ForceFail) { //yield return status2; yield break; } yield return CutState.Continue; } }
internal override bool UnifyWithTerm(Term value, PrologContext context) { return value.UnifyWithAtomicConstant(this, context); }
// ReSharper restore InconsistentNaming private static IEnumerable<CutState> MapListInternal(Symbol functor, object[] args, object list1, object list2, PrologContext context) { // maplist(_, [], []). // ReSharper disable UnusedVariable #pragma warning disable 414, 168, 219 foreach (var ignore in Term.Unify(null, list1)) foreach (var ignore2 in Term.Unify(null, list2)) #pragma warning restore 414, 168, 219 // ReSharper restore UnusedVariable yield return CutState.Continue; // maplist(P, [X | XT], [Y | YT]) :- call(P, X, Y), maplist(P, XT, YT). var x = new LogicVariable(SX); var xT = new LogicVariable(SXt); var y = new LogicVariable(SY); var yT = new LogicVariable(SYt); // ReSharper disable UnusedVariable #pragma warning disable 414, 168, 219 foreach (var ignore in Term.Unify(list1, new Structure(Symbol.PrologListConstructor, x, xT))) foreach (var ignore2 in Term.Unify(list2, new Structure(Symbol.PrologListConstructor, y, yT))) #pragma warning restore 414, 168, 219 { // call(P, X, Y) var realArgs = new object[args.Length + 2]; args.CopyTo(realArgs, 0); realArgs[realArgs.Length - 2] = x; realArgs[realArgs.Length - 1] = y; #pragma warning disable 414, 168, 219 foreach ( var ignore3 in context.KnowledgeBase.Prove(functor, realArgs, context, context.CurrentFrame)) // maplist(P, XT, YT) foreach (var ignore4 in MapListInternal(functor, args, xT, yT, context)) #pragma warning restore 414, 168, 219 // ReSharper restore UnusedVariable yield return CutState.Continue; } }
/// <summary> /// Recopy the term to replace variables. If term contains no variables, no recopying is done. /// </summary> /// <param name="oldVars">Variables to be replaced</param> /// <param name="newVars">The corresponding variables that are replacing the oldVars</param> /// <param name="context">PrologContext to evaluating indexicals</param> /// <param name="evalIndexicals">If true, any indexicals will be replaced with their values.</param> /// <returns>Converted term or original term if not conversion necessary</returns> public abstract object AlphaConvert( List<LogicVariable> oldVars, LogicVariable[] newVars, PrologContext context, bool evalIndexicals);
internal override IEnumerable<CutState> Prove(object[] args, PrologContext context, ushort parentFrame) { object[] goal1Args = null; object[] goal2Args = null; var newVars = new LogicVariable[FreeVariables.Count]; object[] newArgs = Term.AlphaConvertArglist(HeadArgs, FreeVariables, newVars, context, true); // ReSharper disable UnusedVariable #pragma warning disable 414, 168, 219 foreach (bool ignore in Term.UnifyArraysFast(args, newArgs, context)) #pragma warning restore 414, 168, 219 { if (goal1Args == null) goal1Args = Term.AlphaConvertArglist(BodyGoals[0].Arguments, FreeVariables, newVars, context, false); #pragma warning disable 414, 168, 219 foreach (CutState ignoreFreeze in context.ProveAllWokenGoals()) // ReSharper restore UnusedVariable foreach (CutState state1 in context.KnowledgeBase.Prove(BodyGoals[0].Functor, goal1Args, context, parentFrame)) #pragma warning restore 414, 168, 219 { if (state1 == CutState.ForceFail) yield return CutState.ForceFail; if (goal2Args == null) goal2Args = Term.AlphaConvertArglist(BodyGoals[1].Arguments, FreeVariables, newVars, context, false); foreach (CutState state2 in context.KnowledgeBase.Prove(BodyGoals[1].Functor, goal2Args, context, parentFrame)) yield return state2; } } }
/// <summary> /// Called after the variable bound to this Metastructure is unified with a non-variable term. /// </summary> /// <param name="value">The term to which to unify</param> /// <param name="contextOfBinding">Context in which to execute suspended goals.</param> public void MetaTermUnify(object value, PrologContext contextOfBinding) { Debug.Assert(contextOfBinding == Context, "Delayed goal woken in a different context than it was created in."); contextOfBinding.WakeUpGoal(CombineGoals(DelayedGoal, FrozenGoal)); }
/// <summary> /// Create a new set of suspended goals. /// </summary> /// <param name="delayedGoal">Goal to run upon unification with any value.</param> /// <param name="frozenGoal">Goal to run upon unification with a non-variable term.</param> /// <param name="prologContext">Context in which to run goals.</param> public Metastructure(Structure delayedGoal, Structure frozenGoal, PrologContext prologContext) { DelayedGoal = delayedGoal; FrozenGoal = frozenGoal; Context = prologContext; }
private static IEnumerable<CutState> NotImplementation(object[] args, PrologContext context) { if (args.Length != 1) throw new ArgumentCountException("not", args, "goal"); LogicVariable v = Term.FindUninstantiatedVariable(args[0]); if (v != null) throw new InstantiationException(v, "Argument to not must be a ground literal (i.e. contain no unbound variables)."); using (var e = context.Prove(args[0], "Argument to not must be a valid term to prove.").GetEnumerator()) { if (!e.MoveNext() || e.Current == CutState.ForceFail) yield return CutState.Continue; } }
private static IEnumerable<CutState> OnceImplementation(object[] args, PrologContext context) { if (args.Length != 1) throw new ArgumentCountException("once", args, "goal"); #pragma warning disable 414, 168, 219 // ReSharper disable UnusedVariable foreach (var ignore in context.Prove(args[0], "Argument to once/1 must be a valid subgoal.")) #pragma warning restore 414, 168, 219 { // ReSharper restore UnusedVariable yield return CutState.Continue; yield break; } }
private static IEnumerable<CutState> IgnoreImplementation(object[] args, PrologContext context) { if (args.Length != 1) throw new ArgumentCountException("ignore", args, "goal"); using (var e = context.Prove(args[0], "Argument to ignore/n must be a valid subgoal.").GetEnumerator()) { e.MoveNext(); // Ignore whether it succeeded. yield return CutState.Continue; } }
public static object EvalMemberExpression(object obj, object memberExpression, PrologContext context) { obj = Eval(obj, context); memberExpression = Term.Deref(memberExpression); var methodCall = memberExpression as Structure; if (methodCall != null) { // Method call var args = new object[methodCall.Arity]; for (var i = 0; i < args.Length; i++) { args[i] = Eval(methodCall.Argument(i), context); } return obj.InvokeMethod(methodCall.Functor.Name, args); } var propName = memberExpression as Symbol; if (propName != null) { // Field or property reference return obj.GetPropertyOrField(propName.Name); } throw new ArgumentException( "Invalid member expression: " + ISOPrologWriter.WriteToString(new Structure(Symbol.Dot, obj, memberExpression))); }
public static object Eval(object term, PrologContext context) { term = Term.Deref(term); var indexical = term as Indexical; if (indexical != null) return indexical.GetValue(context); var offendingVariable = term as LogicVariable; if (offendingVariable != null) throw new InstantiationException(offendingVariable, "arithmetic expression cannot be evaluated because it includes an uninstantiated variable."); var t = term as Structure; if (t == null) { //var s = term as Symbol; //if (s != null) // throw new BadProcedureException(s, 0); //throw new BadProcedureException(term); return term; // It's a literal. } switch (t.Functor.Name) { case "+": if (t.Arguments.Length != 2) throw new ArgumentCountException("+", t.Arguments, "number1", "number2"); return GenericArithmetic.Add(Eval(t.Arguments[0], context), Eval(t.Arguments[1], context)); case "-": if (t.Arguments.Length == 2) return GenericArithmetic.Subtract(Eval(t.Arguments[0], context), Eval(t.Arguments[1], context)); if (t.Arguments.Length == 1) return GenericArithmetic.Subtract(Eval(t.Arguments[0], context)); throw new ArgumentException("Wrong number of arguments in - expression; should be 1 or 2."); case "*": if (t.Arguments.Length != 2) throw new ArgumentCountException("*", t.Arguments, "number1", "number2"); return GenericArithmetic.Multiply(Eval(t.Arguments[0], context), Eval(t.Arguments[1], context)); case "/": if (t.Arguments.Length != 2) throw new ArgumentCountException("/", t.Arguments, "number1", "number2"); return GenericArithmetic.Divide(Eval(t.Arguments[0], context), Eval(t.Arguments[1], context)); case "mod": if (t.Arguments.Length != 2) throw new ArgumentCountException("mod", t.Arguments, "number1", "number2"); return Convert.ToInt32(Eval(t.Arguments[0], context))% Convert.ToInt32((Eval(t.Arguments[1], context))); case "//": if (t.Arguments.Length != 2) throw new ArgumentCountException("//", t.Arguments, "number1", "number2"); return Convert.ToInt32(Eval(t.Arguments[0], context))/ Convert.ToInt32(Eval(t.Arguments[1], context)); case "sqrt": if (t.Arguments.Length != 1) throw new ArgumentCountException("sqrt", t.Arguments, "number"); return Math.Sqrt(Convert.ToDouble(Eval(t.Arguments[0], context))); case "abs": if (t.Arguments.Length != 1) throw new ArgumentCountException("abs", t.Arguments, "number"); return Math.Abs(Convert.ToDouble(Eval(t.Arguments[0], context))); case "log": if (t.Arguments.Length != 1) throw new ArgumentCountException("log", t.Arguments, "number"); return Math.Log(Convert.ToDouble(Eval(t.Arguments[0], context))); case "exp": if (t.Arguments.Length != 1) throw new ArgumentCountException("exp", t.Arguments, "number"); return Math.Exp(Convert.ToDouble(Eval(t.Arguments[0], context))); case "floor": if (t.Arguments.Length != 1) throw new ArgumentCountException("floor", t.Arguments, "number"); return Math.Floor(Convert.ToDouble(Eval(t.Arguments[0], context))); case "float": if (t.Arguments.Length != 1) throw new ArgumentCountException("floor", t.Arguments, "number"); return Convert.ToSingle(Eval(t.Arguments[0], context)); case "min": if (t.Arguments.Length != 2) throw new ArgumentCountException("min", t.Arguments, "number1", "number2"); return GenericArithmetic.Min(Eval(t.Arguments[0], context), Eval(t.Arguments[1], context)); case "max": if (t.Arguments.Length != 2) throw new ArgumentCountException("max", t.Arguments, "number1", "number2"); return GenericArithmetic.Max(Eval(t.Arguments[0], context), Eval(t.Arguments[1], context)); case "magnitude": { if (t.Arguments.Length != 1) throw new ArgumentCountException("magnitude", t.Arguments, "Vector3"); object v = Eval(t.Argument(0), context); if (!(v is Vector3)) throw new ArgumentTypeException("magnitude", "vector", v, typeof (Vector3)); return ((Vector3) v).magnitude; } case "magnitude_squared": { if (t.Arguments.Length != 1) throw new ArgumentCountException("magnitude_squared", t.Arguments, "Vector3"); object v = Eval(t.Argument(0), context); if (!(v is Vector3)) throw new ArgumentTypeException("magnitude_squared", "vector", v, typeof (Vector3)); return ((Vector3) v).sqrMagnitude; } case "distance": { if (t.Arguments.Length != 2) throw new ArgumentCountException("distance", t.Arguments, "v1", "v2"); object v1 = Eval(t.Argument(0), context); if (v1 is GameObject) v1 = ((GameObject)v1).transform.position; object v2 = Eval(t.Argument(1), context); if (v2 is GameObject) v2 = ((GameObject)v2).transform.position; if (!(v1 is Vector3)) throw new ArgumentTypeException("distance", "v1", v1, typeof (Vector3)); if (!(v2 is Vector3)) throw new ArgumentTypeException("distance", "v2", v2, typeof (Vector3)); return Vector3.Distance((Vector3) v1, (Vector3) v2); } case "distance_squared": { if (t.Arguments.Length != 2) throw new ArgumentCountException("distance_squared", t.Arguments, "v1", "v2"); object v1 = Eval(t.Argument(0), context); if (v1 is GameObject) v1 = ((GameObject)v1).transform.position; object v2 = Eval(t.Argument(1), context); if (v2 is GameObject) v2 = ((GameObject)v2).transform.position; if (!(v1 is Vector3)) throw new ArgumentTypeException("distance_squared", "v1", v1, typeof (Vector3)); if (!(v2 is Vector3)) throw new ArgumentTypeException("distance_squared", "v2", v2, typeof (Vector3)); return Vector3.SqrMagnitude((Vector3) v1 - (Vector3) v2); } case "position": { if (t.Arguments.Length != 1) throw new ArgumentCountException("position", t.Arguments, "gameObject"); var gameObject = Eval(t.Argument(0), context); var go = gameObject as GameObject; if (go==null) throw new ArgumentTypeException("position", "gameObject", gameObject, typeof(GameObject)); return go.transform.position; } case ".": if (t.Arguments.Length != 2) { throw new ArgumentCountException(".", t.Arguments, "object"); } return EvalMemberExpression(t.Arguments[0], t.Arguments[1], context); case "property": { if (t.Arguments.Length != 2) throw new ArgumentCountException("property", t.Arguments, "object", "property_name"); object o = t.Argument(0); if (o is Structure) o = Eval(o, context); var name = t.Argument(1) as Symbol; if (name == null) throw new ArgumentTypeException("property", "property_name", t.Argument(1), typeof(Symbol)); return o.GetPropertyOrField(name.Name); } case "vector": { if (t.Arguments.Length != 3) throw new ArgumentCountException("vector", t.Arguments, "x", "y", "z"); return new Vector3(Convert.ToSingle(Eval(t.Argument(0), context)), Convert.ToSingle(Eval(t.Argument(1), context)), Convert.ToSingle(Eval(t.Argument(2), context))); } case "instance_id": { if (t.Arguments.Length != 1) throw new ArgumentCountException("instance_id", t.Arguments, "game_object"); var arg = t.Argument(0) as UnityEngine.Object; if (arg == null) throw new ArgumentTypeException("instance_id", "object", t.Argument(0), typeof(UnityEngine.Object)); return arg.GetInstanceID(); } default: throw new BadProcedureException(t.Functor, t.Arguments.Length); } }
/// <summary> /// Called after the variable bound to this Metastructure is unified with an unbound variable /// that is not (itself) bound to a Metastructure. /// </summary> /// <param name="l">The logic variable with which to Unify.</param> /// <param name="context">Context in which to execute suspended goals.</param> /// <returns>The Metastructure to bind to the newly aliased variables.</returns> public Metastructure MetaVarUnify(LogicVariable l, PrologContext context) { if (DelayedGoal != null) context.WakeUpGoal(DelayedGoal); return MakeSuspension(null, FrozenGoal); }
internal static System.Collections.Generic.IEnumerable<CutState> Retract(object term, PrologContext context) { ELNode foundNode; ELNodeEnumerator enumerator; if (!TryQuery(term, context, out foundNode, out enumerator)) return PrologPrimitives.FailDriver(); if (foundNode != null) { foundNode.DeleteSelf(); return PrologPrimitives.SucceedDriver(); } return DeleteSuccessive(enumerator); }
public Metastructure(Structure delayedGoal, Structure frozenGoal, PrologContext prologContext, Metastructure old) : this(CombineGoals(delayedGoal, old?.DelayedGoal), CombineGoals(frozenGoal, old?.FrozenGoal), prologContext) { }
internal override IEnumerable<CutState> Prove(object[] args, PrologContext context, ushort parentFrame) { var newVars = new LogicVariable[FreeVariables.Count]; object[] newArgs = Term.AlphaConvertArglist(HeadArgs, FreeVariables, newVars, context, true); // ReSharper disable UnusedVariable #pragma warning disable 414, 168, 219 foreach (bool ignore in Term.UnifyArrays(args, newArgs)) #pragma warning restore 414, 168, 219 // ReSharper restore UnusedVariable yield return CutState.Continue; }
private static IEnumerable<CutState> IfThenImplementation(object[] args, PrologContext context) { if (args.Length != 2) throw new ArgumentCountException("->", args, "if_condition", "then_result"); #pragma warning disable 414, 168, 219 // ReSharper disable UnusedVariable foreach (var ignore in context.Prove(args[0], "Arguments to -> must be valid subgoals.")) // ReSharper restore UnusedVariable { // ReSharper disable UnusedVariable foreach (var ignore2 in context.Prove(args[1], "Arguments to -> must be valid subgoals.")) // ReSharper restore UnusedVariable #pragma warning restore 414, 168, 219 { yield return CutState.Continue; } yield break; } }
internal override IEnumerable<CutState> Prove(object[] args, PrologContext context, ushort parentFrame) { object[] goal1Args = null; object[] goal2Args = null; object[] goal3Args = null; object[] goal4Args = null; object[] goal5Args = null; object[] goal6Args = null; object[] goal7Args = null; object[] goal8Args = null; var newVars = new LogicVariable[FreeVariables.Count]; object[] newArgs = Term.AlphaConvertArglist(HeadArgs, FreeVariables, newVars, context, true); // ReSharper disable UnusedVariable foreach (bool ignore in Term.UnifyArraysFast(args, newArgs, context)) { if (goal1Args == null) goal1Args = Term.AlphaConvertArglist(BodyGoals[0].Arguments, FreeVariables, newVars, context, false); foreach (CutState ignoreFreeze in context.ProveAllWokenGoals()) // ReSharper restore UnusedVariable foreach (CutState state1 in context.KnowledgeBase.Prove(BodyGoals[0].Functor, goal1Args, context, parentFrame)) { if (state1 == CutState.ForceFail) yield return CutState.ForceFail; if (goal2Args == null) goal2Args = Term.AlphaConvertArglist(BodyGoals[1].Arguments, FreeVariables, newVars, context, false); foreach (CutState state2 in context.KnowledgeBase.Prove(BodyGoals[1].Functor, goal2Args, context, parentFrame)) { if (state2 == CutState.ForceFail) yield return CutState.ForceFail; if (goal3Args == null) goal3Args = Term.AlphaConvertArglist(BodyGoals[2].Arguments, FreeVariables, newVars, context, false); foreach (CutState state3 in context.KnowledgeBase.Prove(BodyGoals[2].Functor, goal3Args, context, parentFrame)) { if (state3 == CutState.ForceFail) yield return CutState.ForceFail; if (goal4Args == null) goal4Args = Term.AlphaConvertArglist(BodyGoals[3].Arguments, FreeVariables, newVars, context, false); foreach (CutState state4 in context.KnowledgeBase.Prove(BodyGoals[3].Functor, goal4Args, context, parentFrame)) { if (state4 == CutState.ForceFail) yield return CutState.ForceFail; if (goal5Args == null) goal5Args = Term.AlphaConvertArglist(BodyGoals[4].Arguments, FreeVariables, newVars, context, false); foreach (CutState state5 in context.KnowledgeBase.Prove(BodyGoals[4].Functor, goal5Args, context, parentFrame)) { if (state5 == CutState.ForceFail) yield return CutState.ForceFail; if (goal6Args == null) goal6Args = Term.AlphaConvertArglist(BodyGoals[5].Arguments, FreeVariables, newVars, context, false); foreach (CutState state6 in context.KnowledgeBase.Prove(BodyGoals[5].Functor, goal6Args, context, parentFrame)) { if (state6 == CutState.ForceFail) yield return CutState.ForceFail; if (goal7Args == null) goal7Args = Term.AlphaConvertArglist(BodyGoals[6].Arguments, FreeVariables, newVars, context, false); foreach (CutState state7 in context.KnowledgeBase.Prove(BodyGoals[6].Functor, goal7Args, context, parentFrame)) { if (state7 == CutState.ForceFail) yield return CutState.ForceFail; if (goal8Args == null) goal8Args = Term.AlphaConvertArglist(BodyGoals[7].Arguments, FreeVariables, newVars, context, false); foreach (CutState state8 in context.KnowledgeBase.Prove(BodyGoals[7].Functor, goal8Args, context, parentFrame)) { yield return state8; } } } } } } } } } }
private static IEnumerable<CutState> NotPlusImplementation(object[] args, PrologContext context) { if (args.Length != 1) throw new ArgumentCountException("\\+", args, "goal"); using (var e = context.Prove(args[0], "Argument to \\+ must be a valid term to prove.").GetEnumerator()) { if (!e.MoveNext() || e.Current == CutState.ForceFail) yield return CutState.Continue; } }
private static IEnumerable<CutState> MapListImplementation(object[] args, PrologContext context) { if (args.Length != 3) throw new ArgumentCountException("maplist", args, "predicate", "list1", "list2"); object predicate = Term.Deref(args[0]); var functor = predicate as Symbol; object[] arguments; if (functor != null) { arguments = NoArgs; } else { var t = predicate as Structure; if (t != null) { functor = t.Functor; arguments = t.Arguments; } else throw new ArgumentTypeException("maplist", "predicate", predicate, typeof (Symbol)); } return MapListInternal(functor, arguments, args[1], args[2], context); }