Functor.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (C) 2007-2008, Jeff Thompson
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * * Neither the name of the copyright holder nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  22. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  23. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  24. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  25. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  26. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  27. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. using System;
  31. using System.Collections.Generic;
  32. namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
  33. {
  34. public class Functor : IUnifiable
  35. {
  36. public readonly Atom _name;
  37. public readonly object[] _args;
  38. public Functor(Atom name, object[] args)
  39. {
  40. if (args.Length <= 3)
  41. {
  42. if (args.Length == 0)
  43. throw new Exception("For arity 0 functor, just use name as an Atom");
  44. else if (args.Length == 1)
  45. throw new Exception("For arity 1 functor, use Functor1");
  46. else if (args.Length == 2)
  47. throw new Exception("For arity 2 functor, use Functor2");
  48. else if (args.Length == 3)
  49. throw new Exception("For arity 3 functor, use Functor3");
  50. else
  51. // (This shouldn't happen, but include it for completeness.
  52. throw new Exception("Cannot create a Functor of arity " + args.Length);
  53. }
  54. _name = name;
  55. _args = args;
  56. }
  57. public Functor(string name, object[] args)
  58. : this(Atom.a(name), args)
  59. {
  60. }
  61. /// <summary>
  62. /// Return an Atom, Functor1, Functor2, Functor3 or Functor depending on the
  63. /// length of args.
  64. /// Note that this is different than the Functor constructor which requires
  65. /// the length of args to be greater than 3.
  66. /// </summary>
  67. /// <param name="name"></param>
  68. /// <param name="args"></param>
  69. /// <returns></returns>
  70. public static object make(Atom name, object[] args)
  71. {
  72. if (args.Length <= 0)
  73. return name;
  74. else if (args.Length == 1)
  75. return new Functor1(name, args[0]);
  76. else if (args.Length == 2)
  77. return new Functor2(name, args[0], args[1]);
  78. else if (args.Length == 3)
  79. return new Functor3(name, args[0], args[1], args[2]);
  80. else
  81. return new Functor(name, args);
  82. }
  83. /// <summary>
  84. /// Call the main make, first converting name to an Atom.
  85. /// </summary>
  86. /// <param name="name"></param>
  87. /// <param name="args"></param>
  88. /// <returns></returns>
  89. public static object make(string name, object[] args)
  90. {
  91. return make(Atom.a(name), args);
  92. }
  93. /// <summary>
  94. /// If arg is another Functor, then succeed (yield once) if this and arg have the
  95. /// same name and all functor args unify, otherwise fail (don't yield).
  96. /// If arg is a Variable, then call its unify to unify with this.
  97. /// Otherwise fail (don't yield).
  98. /// </summary>
  99. /// <param name="arg"></param>
  100. /// <returns></returns>
  101. public IEnumerable<bool> unify(object arg)
  102. {
  103. arg = YP.getValue(arg);
  104. if (arg is Functor)
  105. {
  106. Functor argFunctor = (Functor)arg;
  107. if (_name.Equals(argFunctor._name))
  108. return YP.unifyArrays(_args, argFunctor._args);
  109. else
  110. return YP.fail();
  111. }
  112. else if (arg is Variable)
  113. return ((Variable)arg).unify(this);
  114. else
  115. return YP.fail();
  116. }
  117. public override string ToString()
  118. {
  119. string result = _name + "(" + YP.getValue(_args[0]);
  120. for (int i = 1; i < _args.Length; ++i)
  121. result += ", " + YP.getValue(_args[i]);
  122. result += ")";
  123. return result;
  124. }
  125. public bool termEqual(object term)
  126. {
  127. term = YP.getValue(term);
  128. if (term is Functor)
  129. {
  130. Functor termFunctor = (Functor)term;
  131. if (_name.Equals(termFunctor._name) && _args.Length == termFunctor._args.Length)
  132. {
  133. for (int i = 0; i < _args.Length; ++i)
  134. {
  135. if (!YP.termEqual(_args[i], termFunctor._args[i]))
  136. return false;
  137. }
  138. return true;
  139. }
  140. }
  141. return false;
  142. }
  143. public bool lessThan(Functor functor)
  144. {
  145. // Do the equal check first since it is faster.
  146. if (!_name.Equals(functor._name))
  147. return _name.lessThan(functor._name);
  148. if (_args.Length != functor._args.Length)
  149. return _args.Length < functor._args.Length;
  150. for (int i = 0; i < _args.Length; ++i)
  151. {
  152. if (!YP.termEqual(_args[i], functor._args[i]))
  153. return YP.termLessThan(_args[i], functor._args[i]);
  154. }
  155. return false;
  156. }
  157. public bool ground()
  158. {
  159. for (int i = 0; i < _args.Length; ++i)
  160. {
  161. if (!YP.ground(_args[i]))
  162. return false;
  163. }
  164. return true;
  165. }
  166. public void addUniqueVariables(List<Variable> variableSet)
  167. {
  168. for (int i = 0; i < _args.Length; ++i)
  169. YP.addUniqueVariables(_args[i], variableSet);
  170. }
  171. public object makeCopy(Variable.CopyStore copyStore)
  172. {
  173. object[] argsCopy = new object[_args.Length];
  174. for (int i = 0; i < _args.Length; ++i)
  175. argsCopy[i] = YP.makeCopy(_args[i], copyStore);
  176. return new Functor(_name, argsCopy);
  177. }
  178. }
  179. }