PageRenderTime 26ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/YieldProlog/Modules/Functor.cs

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