PageRenderTime 50ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/YieldProlog/Modules/Atom.cs

https://bitbucket.org/VirtualReality/optional-modules
C# | 215 lines | 131 code | 19 blank | 65 comment | 36 complexity | 8cf92bc78d0c9742141471dd2cdfdcb1 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. using System.Text;
  30. namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
  31. {
  32. public class Atom : IUnifiable
  33. {
  34. private static Dictionary<string, Atom> _atomStore = new Dictionary<string, Atom>();
  35. public readonly string _name;
  36. public readonly Atom _module;
  37. /// <summary>
  38. /// You should not call this constructor, but use Atom.a instead.
  39. /// </summary>
  40. /// <param name="name"></param>
  41. /// <param name="module"></param>
  42. private Atom(string name, Atom module)
  43. {
  44. _name = name;
  45. _module = module;
  46. }
  47. /// <summary>
  48. /// Return the unique Atom object for name where module is null. You should use this to create
  49. /// an Atom instead of calling the Atom constructor.
  50. /// </summary>
  51. /// <param name="name"></param>
  52. /// <returns></returns>
  53. public static Atom a(string name)
  54. {
  55. Atom atom;
  56. if (!_atomStore.TryGetValue(name, out atom))
  57. {
  58. atom = new Atom(name, null);
  59. _atomStore[name] = atom;
  60. }
  61. return atom;
  62. }
  63. /// <summary>
  64. /// Return an Atom object with the name and module. If module is null or Atom.NIL,
  65. /// this behaves like Atom.a(name) and returns the unique object where the module is null.
  66. /// If module is not null or Atom.NIL, this may or may not be the same object as another Atom
  67. /// with the same name and module.
  68. /// </summary>
  69. /// <param name="name"></param>
  70. /// <param name="module"></param>
  71. /// <returns></returns>
  72. public static Atom a(string name, Atom module)
  73. {
  74. if (module == null || module == Atom.NIL)
  75. return a(name);
  76. return new Atom(name, module);
  77. }
  78. /// <summary>
  79. /// If Obj is an Atom unify its _module with Module. If the Atom's _module is null, use Atom.NIL.
  80. /// </summary>
  81. /// <param name="Atom"></param>
  82. /// <param name="Module"></param>
  83. /// <returns></returns>
  84. public static IEnumerable<bool> module(object Obj, object Module)
  85. {
  86. Obj = YP.getValue(Obj);
  87. if (Obj is Atom)
  88. {
  89. if (((Atom)Obj)._module == null)
  90. return YP.unify(Module, Atom.NIL);
  91. else
  92. return YP.unify(Module, ((Atom)Obj)._module);
  93. }
  94. return YP.fail();
  95. }
  96. public static readonly Atom NIL = Atom.a("[]");
  97. public static readonly Atom DOT = Atom.a(".");
  98. public static readonly Atom F = Atom.a("f");
  99. public static readonly Atom SLASH = Atom.a("/");
  100. public static readonly Atom HAT = Atom.a("^");
  101. public static readonly Atom RULE = Atom.a(":-");
  102. public IEnumerable<bool> unify(object arg)
  103. {
  104. arg = YP.getValue(arg);
  105. if (arg is Atom)
  106. return Equals(arg) ? YP.succeed() : YP.fail();
  107. else if (arg is Variable)
  108. return ((Variable)arg).unify(this);
  109. else
  110. return YP.fail();
  111. }
  112. public void addUniqueVariables(List<Variable> variableSet)
  113. {
  114. // Atom does not contain variables.
  115. }
  116. public object makeCopy(Variable.CopyStore copyStore)
  117. {
  118. // Atom does not contain variables that need to be copied.
  119. return this;
  120. }
  121. public bool termEqual(object term)
  122. {
  123. return Equals(YP.getValue(term));
  124. }
  125. public bool ground()
  126. {
  127. // Atom is always ground.
  128. return true;
  129. }
  130. public override bool Equals(object obj)
  131. {
  132. if (obj is Atom)
  133. {
  134. if (_module == null && ((Atom)obj)._module == null)
  135. // When _declaringClass is null, we always use an identical object from _atomStore.
  136. return this == obj;
  137. // Otherwise, ignore _declaringClass and do a normal string compare on the _name.
  138. return _name == ((Atom)obj)._name;
  139. }
  140. return false;
  141. }
  142. public override string ToString()
  143. {
  144. return _name;
  145. }
  146. public override int GetHashCode()
  147. {
  148. // Debug: need to check _declaringClass.
  149. return _name.GetHashCode();
  150. }
  151. public string toQuotedString()
  152. {
  153. if (_name.Length == 0)
  154. return "''";
  155. else if (this == Atom.NIL)
  156. return "[]";
  157. StringBuilder result = new StringBuilder(_name.Length);
  158. bool useQuotes = false;
  159. foreach (char c in _name)
  160. {
  161. int cInt = (int)c;
  162. if (c == '\'')
  163. {
  164. result.Append("''");
  165. useQuotes = true;
  166. }
  167. else if (c == '_' || cInt >= (int)'a' && cInt <= (int)'z' ||
  168. cInt >= (int)'A' && cInt <= (int)'Z' || cInt >= (int)'0' && cInt <= (int)'9')
  169. result.Append(c);
  170. else
  171. {
  172. // Debug: Need to handle non-printable chars.
  173. result.Append(c);
  174. useQuotes = true;
  175. }
  176. }
  177. if (!useQuotes && (int)_name[0] >= (int)'a' && (int)_name[0] <= (int)'z')
  178. return result.ToString();
  179. else
  180. {
  181. // Surround in single quotes.
  182. result.Append('\'');
  183. return "'" + result;
  184. }
  185. }
  186. /// <summary>
  187. /// Return true if _name is lexicographically less than atom._name.
  188. /// </summary>
  189. /// <param name="atom"></param>
  190. /// <returns></returns>
  191. public bool lessThan(Atom atom)
  192. {
  193. return _name.CompareTo(atom._name) < 0;
  194. }
  195. }
  196. }