// try to bind the variable associated with the last 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);
      }
      // try to bind the range specification variable (if present) to the range last.
      // 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;
      }
      // 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 last,
        // 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, 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 last 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;
      }
      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 last, 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
        }
      }
      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;
      }
Пример #7
0
    public bool Retract(Term t, VarStack varStack, Term where)
    {
      string key = t.KbKey;

      if (predefineds.Contains(key))
        PrologIO.Error("retract of predefined predicate {0} not allowed", key);

      PredicateDescr pd = this[key];

      if (pd == null) return false;

#if persistent
      if (pd is PersistentPredDescr)
      {
        ((PersistentPredDescr)pd).Retract (t, varStack, where);

        return true;
      }
#endif

      ClauseNode c = pd.GetClauseList(null, null);
      ClauseNode prevc = null;
      Term cleanTerm;
      int top;

      while (c != null)
      {
        cleanTerm = c.Term.CleanCopy();

        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)
        }

        Term s;
        for (int i = varStack.Count - top; i > 0; i--) // unbind all vars that got bound by the above Unification
        {
          s = (Term)varStack.Pop();
          s.Unbind();
        }

        prevc = c;
        c = c.NextClause;
      }

      ResolveIndices();

      return false;
    }
Пример #8
0
    public bool RetractAll(Term t, VarStack varStack) // should *always* return true ?????
    {
      // remark: first-argument indexing is not affected by deleting clauses

      string key = t.KbKey;

      if (predefineds.Contains(key))
        PrologIO.Error("retract of predefined predicate {0} not allowed", key);

      PredicateDescr pd = this[key];

      if (pd == null) return true;

#if persistent
      if (pd is PersistentPredDescr)
      {
        ((PersistentPredDescr)pd).Retract (t, varStack, null);

        return true;  /////////////JPO persistent retract always to succeed ????
      }
#endif

      ClauseNode c = pd.GetClauseList(null, null);
      ClauseNode prevc = null;
      bool match = false;

      while (c != null)
      {
        Term cleanTerm = c.Term.CleanCopy();

        if (cleanTerm.Unifiable(t, varStack)) // match found -- remove this term from the chain
        {
          match = true; // to indicate that at least one term 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 (); // rebuild by ResolveIndices()
#endif
        pd.AdjustClauseListEnd();
        ResolveIndices();
      }

      return true;
    }
Пример #9
0
    public override void Retract (Term Term, VarStack stack, Term where)
    {
      StringBuilder deleteStat = new StringBuilder ("DELETE FROM " + dbEntity);
      TableColumnCollection tcc = (TableColumnCollection)MetaDataCollection;
      ListDictionary varNrs = new ListDictionary ();
      bool first = true;

      for (int i = 0; i < Term.Arity; i++)
      {
        Term arg = Term.Arg (i);
        string colName = tcc [i].Name;

        if (arg.IsAtom || arg.IsString)
          deleteStat.AppendFormat ("{0} {1}={2}", Conj (ref first), colName, Utils.EnsureQuoted (arg.Functor));
        else if (arg.IsNumber)
          deleteStat.AppendFormat ("{0} {1}={2}", Conj (ref first), colName, arg.Functor);
        else if (arg.IsVar)
        {
          object prevColNo;
          // check whether value occurred as argument before (anonymous vars always have a unique varNo)
          if ((prevColNo = varNrs [arg.VarNo]) != null) // ... yes
            deleteStat.AppendFormat ("{0} {1}={2}", Conj (ref first), tcc [(int)prevColNo].Name, colName);
          varNrs [arg.VarNo] = i; // save for comparison with next argument(s)
        }
        else if (!arg.IsVar)
          IO.Error ("Illegal argument {0} for retract of persistent clause {1}", arg, Term);
      }

      if (where != null) // add the extra where-clause (if any)
      {
        // Copy the ref-table of column numers into a ref-table of corresponding column names
        ListDictionary varNames = new ListDictionary (); // ... in-situ modifications of Collection-values is not possible
        foreach (DictionaryEntry de in varNrs) varNames [(int)de.Key] = tcc [(int)de.Value].Name;
        deleteStat.AppendFormat ("{0} {1}", Conj (ref first), where.ToStringSql (varNames));
      }

      if (first)
        IO.Warning ("Retract -- DELETE without WHERE -- will NOT be executed !!!!!!!!");
      else
        ExecuteSqlCommand (deleteStat.ToString ());
    }
Пример #10
0
 public override void Retract (Term Term, VarStack stack, Term where)
 {
   IO.Error ("Unable to delete from '{0}' (not a table)", dbEntity);
 }
Пример #11
0
 public abstract void Retract (Term Term, VarStack stack, Term where);
Пример #12
0
    public void NumberVars(ref int k, VarStack s)
    {
      Term t;

      if (hasValue)
      {
        if (isUnified)
          ULink.NumberVars(ref k, s);
        else if (arity != 0) // hasValue & not isUnified
          for (int i = 0; i < arity; i++) args[i].NumberVars(ref k, s);
      }
      else // unbound variable
      {
        Term a = new Term(k.ToString(), FType.number);
        k++;
        t = new Term("'$VAR'", a, OType.noop, 0);
        this.Unify(t, s);
      }
    }
Пример #13
0
    public bool Unifiable(Term t, VarStack varStack) // as Unify, but does not actually bind
    {
      int top = varStack.Count;

      bool result = Unify(t, varStack);

      for (int i = varStack.Count - top; i > 0; i--) // unbind all varNoSet that got bound by Unify
      {
        Term s = (Term)varStack.Pop();
        s.Unbind();
      }

      return result;
    }
Пример #14
0
    public bool Unify(Term t, VarStack varStack, bool occurCheck)
    {
      if (isUnified) return ULink.Unify(t, varStack, occurCheck);
      if (t.isUnified) return Unify(t.ULink, varStack, occurCheck);
      //Interpreter.UCount++;

      if (hasValue)
      {
        if (t.hasValue)
        {
          if (_functor.Equals(t._functor) && arity == t.Arity) // => two cuts will unify as well
          {
            for (int i = 0; i < arity; i++) if (!args[i].Unify(t.Arg(i), varStack, occurCheck)) return false;

            return true;
          }
          else
            return false;
        }
        // t is an unbound variable (add occur check here if deemed necessary)
        t.Bind(this);
        varStack.Push(t);
      }
      else // 'this' is an unbound variable. Add occur check here if deemed necessary
      {
        this.Bind(t);
        varStack.Push(this);
      }

      return true;
    }
Пример #15
0
 // UNIFICATION
 // The stack is used to store the variables and choice points that are bound by the unification.
 // This is needed when backtracking. Unify does not do any unbinding in case of failure. This will
 // be done when backtracking.
 public bool Unify(Term t, VarStack varStack)
 {
   return Unify(t, varStack, false);
 }