public override bool Unify(BaseTerm t, VarStack varStack) { NextUnifyCount(); if (!((t = t.ChainEnd()) is ListPatternElem)) { return(false); // should never occur } #if old if (isNegSearch != ((ListPatternElem)t).isNegSearch) { return(false); } #endif for (int i = 0; i < arity; i++) { if (!((args[i] == null && t.Args[i] == null) || args[i].Unify(t.Args[i], varStack))) { return(false); } } return(true); }
public override bool Unify(BaseTerm t, VarStack varStack) { if ((t = t.ChainEnd()) is Variable) // t not unified { ((Variable)t).Bind(this); varStack.Push(t); return(true); } if (t is ListPatternTerm && arity == t.Arity) // two ListPatternTerms match if their rangeTerms match { for (int i = 0; i < arity; i++) { if (!args[i].Unify(t.Args[i], varStack)) { return(false); } } return(true); } if (t is ListTerm) { pattern = args; // pattern is searched ... target = ((ListTerm)t).ToList(); // ... in target int ip = 0; int it = 0; return(UnifyTailEx(ip, it, varStack)); } return(false); }
public static bool SetWorkingDirectory(BaseTerm term, VarStack varStack) { if (term.Arity == 0) { workingDirectory = GetConfigSetting("WorkingDirectory", null); IO.Message("Working directory set to '{0}'", WorkingDirectory); return(true); } BaseTerm t0 = term.Arg(0); if (t0.IsVar) { t0.Unify(new StringTerm(workingDirectory), varStack); // symbolic names return(true); } string wd = Utils.DirectoryNameFromTerm(t0); if (wd == null) { IO.Error("Illegal name '{0}' for working directory", t0.FunctorToString); return(false); } workingDirectory = wd; IO.Message("Working directory set to '{0}'", WorkingDirectory); return(true); }
public override bool Unify(BaseTerm t, VarStack varStack) { if (t is Variable) { return(t.Unify(this, varStack)); } NextUnifyCount(); const double eps = 1.0e-6; // arbitrary, cosmetic if (t is DecimalTerm) { return(Math.Abs(im) < eps && Math.Abs(re - ((DecimalTerm)t).ValueD) < eps); } if (t is ComplexTerm) { return(Math.Abs(re - ((ComplexTerm)t).Re) < eps && Math.Abs(im - ((ComplexTerm)t).Im) < eps); } //if (t is ComplexTerm) // return ( re == ((ComplexTerm)t).Re && im == ((ComplexTerm)t).Im ); return(false); }
public ClauseIterator(PredicateTable predTable, BaseTerm clauseHead, VarStack varStack) { this.pd = predTable[clauseHead.Key]; // null if not found this.clauseHead = clauseHead; this.varStack = varStack; iterator = GetEnumerator(); }
public bool IsUnifiableWith(BaseTerm t, VarStack varStack) // as Unify, but does not actually bind { int marker = varStack.Count; bool result = Unify(t, varStack); UnbindToMarker(varStack, marker); return(result); }
public NodeIterator(BaseTerm root, BaseTerm pattern, BaseTerm minLenTerm, BaseTerm maxLenTerm, BaseTerm path, VarStack varStack) { this.root = root; this.pattern = pattern; this.varStack = varStack; this.minLenTerm = minLenTerm; this.maxLenTerm = maxLenTerm; this.path = path; iterator = GetEnumerator(); }
public static void UnbindToMarker(VarStack varStack, int marker) { for (int i = varStack.Count - marker; i > 0; i--) // unbind all vars that got bound by Unify { Variable v = varStack.Pop() as Variable; if (v != null) { v.Unbind(); } } }
public Variable DeclareGlobalVariable(string name, DObject val) { if (variables.ContainsKey(name)) { throw new InterpreterException(interpreter.CurrentToken, "Global variable already exists: " + name); } var stack = new VarStack(); var v = new Variable(val, -1); stack.Push(v); variables.Add(name, stack); return(v); }
public static string VarList(VarStack varStack) // debugging only { StringBuilder result = new StringBuilder(); foreach (object v in varStack.ToArray()) { if (v != null && v is Variable) { result.AppendLine(string.Format(">> {0} = {1}", ((Variable)v).Name, (Variable)v)); } } return(result.ToString()); }
public ReadOnlyVariable DeclareReadOnly(string name, DObject val) { var v = new ReadOnlyVariable(val, interpreter.depth); if (!variables.ContainsKey(name)) { var stack = new VarStack(); stack.Push(v); variables.Add(name, stack); } variables[name].Push(v); return(v); }
public IEnumerable <VarData> SubLocalVars() { if (CallDepth > 0) { int i = VarIndexStack[CallDepth - 1]; return(VarStack.Skip(i + 1).Take(VarIndex - i)); } else if (VarIndex > 0) { return(VarStack.Take(VarIndex + 1)); } else { return(Enumerable.Empty <VarData>()); } }
public Variable DeclareLocal(string name, DObject val) { val = val == null ? DUndefined.instance : val; var v = new Variable(val, interpreter.depth); if (!variables.ContainsKey(name)) { var stack = new VarStack(); stack.Push(v); variables.Add(name, stack); } variables[name].Push(v); return(v); }
private AltLoopStatus TryOneAlternative(int ip, VarStack varStack, ListPatternElem e, int k, int marker, ListTerm RangeList, int i, BaseTerm t, ref bool negSearchSucceeded, BaseTerm searchTerm) { bool unified = searchTerm.Unify(t, varStack); if (e.IsNegSearch) // none of the terms in the inner loop may match. ~(a | b | c) = ~a & ~b & ~c { if (unified) // ... no point in investigating the other alternatives if one does { negSearchSucceeded = false; return(AltLoopStatus.Break); // don't try the other alternatives } return(AltLoopStatus.TryNextDown); // non of the downranges matches may lead to a success } else { if (unified && // we found a match. Unify, and TryBindingAltListVarToMatch(e.AltListBindVar, t, varStack) && // bind the AltListBindVar to the match TryBindingRangeRelatedVars(e, i, RangeList, varStack)) // bind the range to the range variables { if (ip == pattern.Length - 1) // this was the last pattern element { if (k == target.Count - 1) // both pattern and target exhausted { return(AltLoopStatus.MatchFound); } } else if (UnifyTailEx(ip + 1, k + 1, varStack)) // now deal with the rest { return(AltLoopStatus.MatchFound); } } // if we arrive here, it was not possible to ... // (1) ... unify the range's SearchTerm with the target element, or // (2) ... unify the range variable with the range list, or // (3) ... successfully process the rest of the pattern and target // Now unbind and try matching with the next target element BaseTerm.UnbindToMarker(varStack, marker); return(AltLoopStatus.TryNextDown); // try the next downrange match } }
// UNIFICATION // The stack is used to store the variables and choice points that are bound // by the unification. This is required for backtracking. Unify does not do // any unbinding in case of failure. This will be done during backtracking. // refUnifyCount: can be used for calculating the 'cost' of a predicate Call public virtual bool Unify(BaseTerm t, VarStack varStack) { NextUnifyCount(); if (t.IsUnified) { return(this.Unify(t.ChainEnd(), varStack)); } if (t is Variable) // t not unified { ((Variable)t).Bind(this); varStack.Push(t); return(true); } if (t is ListPatternTerm) { return(t.Unify(this, varStack)); } if (termType != t.termType) { return(false); // gives a slight improvement } if (functor.Equals(t.functor) && arity == t.arity) { for (int i = 0; i < arity; i++) { if (!args[i].Unify(t.args[i], varStack)) { return(false); } } return(true); } return(false); }
public void NumberVars(ref int k, VarStack s) { if (IsVar) { this.Unify(new CompoundTerm(NUMVAR, new DecimalTerm(k++)), s); } else { if (IsUnified) { ChainEnd().NumberVars(ref k, s); } else if (arity != 0) // nonvar & not isUnified { for (int i = 0; i < arity; i++) { args[i].NumberVars(ref k, s); } } } }
// try to bind the variable associated with the list of search alternatives // (t1|t2|...|tn) to the target term found matching one of these alternatives bool TryBindingAltListVarToMatch(BaseTerm AltListVar, BaseTerm searchTerm, VarStack varStack) { if (AltListVar == null) { return(true); } return(AltListVar.Unify(searchTerm, varStack)); }
// each call processes one element of pattern[] bool UnifyTailEx(int ip, int it, VarStack varStack) { ListPatternElem e = (ListPatternElem)pattern[ip]; Variable rangeSpecVar = (Variable)e.RangeBindVar; NodeIterator subtreeIterator; int k; int marker; ListTerm RangeList = null; BaseTerm tail = null; int minLen; // minimum required range length (number of range elements) int maxLen; // maximum possible ... if (!DoLowerAndUpperboundChecks(ip, it, out minLen, out maxLen)) { return(false); } // scan the minimal number of range elements. Add them to the range list, // i.e. the last variable (if present) preceding the '{ , }' for (int i = 0; i < minLen; i++) { if ((k = it + i) >= target.Count) { return(false); } AppendToRangeList(ref RangeList, rangeSpecVar, target[k], ref tail); } marker = varStack.Count; // register the point to which we must possibly undo unifications if (e.HasSearchTerm) { // scan the elements up to the maximum range length, and the element immediately thereafter for (int i = minLen; i <= maxLen; i++) { BaseTerm t = null; k = it + i; if (k == target.Count) { return(false); } bool negSearchSucceeded = true; // iff none of the alternative term matches the target term for (int j = 4; j < e.Args.Length; j++) // scan all AltSearchTerm alternatives (separated by '|') { BaseTerm searchTerm = e.AltSearchTerms[j]; DownRepFactor downRepFactor = null; // e.downRepFactor [j]; t = target[k]; AltLoopStatus status = AltLoopStatus.TryNextAlt; if (downRepFactor == null) { status = TryOneAlternative(ip, varStack, e, k, marker, RangeList, i, t, ref negSearchSucceeded, searchTerm); if (status == AltLoopStatus.MatchFound) { return(true); } } else // traverse the downRepFactor tree, which in principle may yield more than one match { subtreeIterator = new NodeIterator(t, searchTerm, downRepFactor.minLenTerm, downRepFactor.maxLenTerm, false, downRepFactor.bindVar, varStack); foreach (BaseTerm match in subtreeIterator) // try -- if necessary -- each tree match with the current search term { status = TryOneAlternative(ip, varStack, e, k, marker, RangeList, i, match, ref negSearchSucceeded, searchTerm); if (status == AltLoopStatus.MatchFound) { return(true); } if (status == AltLoopStatus.Break) { break; } } } if (status == AltLoopStatus.Break) { break; } } // at this point sufficient alternatives have been tried if (e.IsNegSearch && negSearchSucceeded) // none of the terms matched => ok if binding succeeds { if (!TryBindingAltListVarToMatch(e.AltListBindVar, t, varStack) || // bind the AltListBindVar to the match !TryBindingRangeRelatedVars(e, i, RangeList, varStack)) // bind the range to the range variables { return(false); // binding failed } if (ip == pattern.Length - 1) // this was the last pattern element { if (k == target.Count - 1) // both pattern and target exhausted { return(true); } } else if (UnifyTailEx(ip + 1, k + 1, varStack)) // now deal with the rest { return(true); } } else if (i < maxLen) // append the rejected term to the range list and go try the next term { AppendToRangeList(ref RangeList, rangeSpecVar, t, ref tail); } } } else // a range without a subsequent search term (so followed by another range or end of pattern) { for (int i = minLen; i <= maxLen; i++) { k = it + i; if (k == target.Count) // ok, target[k] does not exist, end of target hit { return(TryBindingRangeRelatedVars(e, i, RangeList, varStack)); // i is actual range length } // k is ok if (i < maxLen) { AppendToRangeList(ref RangeList, rangeSpecVar, target[k], ref tail); } // now deal with the rest if (TryBindingRangeRelatedVars(e, i, RangeList, varStack) && UnifyTailEx(ip + 1, k, varStack)) { return(true); } } } // If we arrive here, no matching term was found in or immediately after the permitted range. // Therefore, undo any unifications made locally in this method and return with failure. if (marker != 0) { BaseTerm.UnbindToMarker(varStack, marker); } return(false); }
public bool Retract(BaseTerm t, VarStack varStack, BaseTerm where) { string key = t.Key; if (predefineds.Contains(key)) { IO.Error("retract of predefined predicate {0} not allowed", key); } PredicateDescr pd = this[key]; if (pd == null) { return(false); } InvalidateCrossRef(); ClauseNode c = pd.ClauseList; ClauseNode prevc = null; BaseTerm cleanTerm; int top; while (c != null) { cleanTerm = c.Head.Copy(); top = varStack.Count; if (cleanTerm.Unify(t, varStack)) // match found -- remove this term from the chain { if (prevc == null) // remove first clause { if (c.NextClause == null) // we are about to remove the last remaining clause for this predicate { predTable.Remove(key); // ... so remove its PredicateDescr as well #if arg1index pd.CreateFirstArgIndex(); // re-create #endif ResolveIndices(); } else { pd.SetClauseListHead(c.NextClause); } } else // not the first { prevc.NextClause = c.NextClause; prevc = c; pd.AdjustClauseListEnd(); #if arg1index pd.CreateFirstArgIndex(); // re-create #endif } return(true); // possible bindings must stay intact (e.g. if p(a) then retract(p(X)) yields X=a) } Variable s; for (int i = varStack.Count - top; i > 0; i--) // unbind all vars that got bound by the above Unification { s = (Variable)varStack.Pop(); s.Unbind(); } prevc = c; c = c.NextClause; } ResolveIndices(); return(false); }
public bool RetractAll(BaseTerm t, VarStack varStack) { // remark: first-argument indexing is not affected by deleting clauses string key = t.Key; if (predefineds.Contains(key)) { IO.Error("retract of predefined predicate {0} not allowed", key); } PredicateDescr pd = this[key]; if (pd == null) { return(true); } ClauseNode c = pd.ClauseList; ClauseNode prevc = null; bool match = false; while (c != null) { BaseTerm cleanTerm = c.Term.Copy(); if (cleanTerm.IsUnifiableWith(t, varStack)) // match found -- remove this head from the chain { match = true; // to indicate that at least one head was found if (prevc == null) // remove first clause { if (c.NextClause == null) // we are about to remove the last remaining clause for this predicate { predTable.Remove(key); // ... so remove its PredicateDescr as well break; } else { pd.SetClauseListHead(c.NextClause); } } else // not the first { prevc.NextClause = c.NextClause; prevc = c; } } else { prevc = c; } c = c.NextClause; } if (match) { #if arg1index pd.DestroyFirstArgIndex(); // rebuilt by ResolveIndices() #endif pd.AdjustClauseListEnd(); ResolveIndices(); } return(true); }
// try to bind the range specification variable (if present) to the range list. // if the minimun or the maximum range length was a variable, then bind it to the actual length just found bool TryBindingRangeRelatedVars(ListPatternElem g, int rangeLength, ListTerm RangeList, VarStack varStack) { if (g.MinLenTerm.IsVar) { g.MinLenTerm.Unify(new DecimalTerm(rangeLength), varStack); } if (g.MaxLenTerm.IsVar) { g.MaxLenTerm.Unify(new DecimalTerm(rangeLength), varStack); } if (g.RangeBindVar != null) { if (RangeList == null) { RangeList = ListTerm.EMPTYLIST; } if (!g.RangeBindVar.Unify(RangeList, varStack)) { return(false); // alas, the same range var was apparently used & bound earlier in the pattern } } return(true); }