/interpreter/tags/at2dist110511/src/edu/vub/at/objects/natives/NATNumeric.java

http://ambienttalk.googlecode.com/ · Java · 287 lines · 175 code · 21 blank · 91 comment · 6 complexity · 1836fc5b2b585bfdf6c06973d4c79bb3 MD5 · raw file

  1. /**
  2. * AmbientTalk/2 Project
  3. * NATNumeric.java created on 18-aug-2006 at 11:06:11
  4. * (c) Programming Technology Lab, 2006 - 2007
  5. * Authors: Tom Van Cutsem & Stijn Mostinckx
  6. *
  7. * Permission is hereby granted, free of charge, to any person
  8. * obtaining a copy of this software and associated documentation
  9. * files (the "Software"), to deal in the Software without
  10. * restriction, including without limitation the rights to use,
  11. * copy, modify, merge, publish, distribute, sublicense, and/or
  12. * sell copies of the Software, and to permit persons to whom the
  13. * Software is furnished to do so, subject to the following
  14. * conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be
  17. * included in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  20. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  21. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  23. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  24. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  26. * OTHER DEALINGS IN THE SOFTWARE.
  27. */
  28. package edu.vub.at.objects.natives;
  29. import java.util.HashMap;
  30. import edu.vub.at.exceptions.InterpreterException;
  31. import edu.vub.at.exceptions.XTypeMismatch;
  32. import edu.vub.at.objects.ATBoolean;
  33. import edu.vub.at.objects.ATContext;
  34. import edu.vub.at.objects.ATFraction;
  35. import edu.vub.at.objects.ATMethod;
  36. import edu.vub.at.objects.ATNumeric;
  37. import edu.vub.at.objects.ATObject;
  38. import edu.vub.at.objects.ATTable;
  39. import edu.vub.at.objects.ATText;
  40. import edu.vub.at.objects.coercion.NativeTypeTags;
  41. import edu.vub.at.objects.grammar.ATSymbol;
  42. import edu.vub.at.objects.mirrors.DirectNativeMethod;
  43. import edu.vub.at.objects.natives.grammar.AGExpression;
  44. /**
  45. * A common superclass of both numbers and fractions to factor out common base-level behaviour.
  46. *
  47. * @author tvc
  48. */
  49. public abstract class NATNumeric extends AGExpression implements ATNumeric {
  50. /**
  51. * Template method that should return the value of the underlying number or fraction as a double
  52. */
  53. protected abstract double getJavaValue();
  54. public NATNumeric asNativeNumeric() throws XTypeMismatch {
  55. return this;
  56. }
  57. public ATTable meta_typeTags() throws InterpreterException {
  58. return NATTable.of(NativeTypeTags._NUMERIC_);
  59. }
  60. // numbers and fractions are singletons
  61. public ATObject meta_clone() throws InterpreterException {
  62. return this;
  63. }
  64. // trigonometric functions
  65. /**
  66. * NUM(n).cos() => FRC(Math.cos(n))
  67. */
  68. public ATFraction base_cos() {
  69. return NATFraction.atValue(Math.cos(getJavaValue()));
  70. }
  71. /**
  72. * NUM(n).sin() => FRC(Math.sin(n))
  73. */
  74. public ATFraction base_sin() {
  75. return NATFraction.atValue(Math.sin(getJavaValue()));
  76. }
  77. /**
  78. * NUM(n).tan() => FRC(Math.tan(n))
  79. */
  80. public ATFraction base_tan() {
  81. return NATFraction.atValue(Math.tan(getJavaValue()));
  82. }
  83. /**
  84. * NUM(n).log() => FRC(log(e,n))
  85. */
  86. public ATFraction base_log() {
  87. return NATFraction.atValue(Math.log(getJavaValue()));
  88. }
  89. /**
  90. * NUM(n).sqrt() => FRC(Math.sqrt(n))
  91. */
  92. public ATFraction base_sqrt() {
  93. return NATFraction.atValue(Math.sqrt(getJavaValue()));
  94. }
  95. /**
  96. * NUM(n).expt(NUM(e)) => FRC(Math.pow(n,e))
  97. */
  98. public ATFraction base_expt(ATNumeric pow) throws InterpreterException {
  99. return NATFraction.atValue(Math.pow(getJavaValue(), pow.asNativeNumeric().getJavaValue()));
  100. }
  101. // Comparable 'mixin' based on <=>
  102. /**
  103. * a < b iff (a <=> b) == -1
  104. */
  105. public ATBoolean base__opltx_(ATNumeric other) throws InterpreterException {
  106. return NATBoolean.atValue(this.base__opltx__opeql__opgtx_(other).equals(NATNumber.MONE));
  107. }
  108. /**
  109. * a > b iff (a <=> b) == +1
  110. */
  111. public ATBoolean base__opgtx_(ATNumeric other) throws InterpreterException {
  112. return NATBoolean.atValue(this.base__opltx__opeql__opgtx_(other).equals(NATNumber.ONE));
  113. }
  114. /**
  115. * a <= b iff (a <=> b) != +1
  116. */
  117. public ATBoolean base__opltx__opeql_(ATNumeric other) throws InterpreterException {
  118. return NATBoolean.atValue(! this.base__opltx__opeql__opgtx_(other).equals(NATNumber.ONE));
  119. }
  120. /**
  121. * a >= b iff (a <=> b) != -1
  122. */
  123. public ATBoolean base__opgtx__opeql_(ATNumeric other) throws InterpreterException {
  124. return NATBoolean.atValue(! this.base__opltx__opeql__opgtx_(other).equals(NATNumber.MONE));
  125. }
  126. /**
  127. * a = b iff (a <=> b) == 0
  128. */
  129. public ATBoolean base__opeql_(ATNumeric other) throws InterpreterException {
  130. return NATBoolean.atValue(this.base__opltx__opeql__opgtx_(other).equals(NATNumber.ZERO));
  131. }
  132. /**
  133. * a != b iff (a <=> b) != 0
  134. */
  135. public ATBoolean base__opnot__opeql_(ATObject other) throws InterpreterException {
  136. if (other instanceof ATNumeric) {
  137. return NATBoolean.atValue(! this.base__opltx__opeql__opgtx_(other.asNativeNumeric()).equals(NATNumber.ZERO));
  138. } else {
  139. return NATBoolean._TRUE_;
  140. }
  141. }
  142. /**
  143. * This hashmap stores all native methods of native AmbientTalk numerics.
  144. * It is populated when this class is loaded, and shared between all
  145. * AmbientTalk actors on this VM. This is safe, since {@link DirectNativeMethod}
  146. * instances are all immutable.
  147. */
  148. private static final HashMap<String, ATMethod> _meths = new HashMap<String, ATMethod>();
  149. // initialize NATNumeric methods
  150. static {
  151. _meths.put("cos", new DirectNativeMethod("cos") {
  152. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  153. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  154. checkArity(args, 0);
  155. return self.base_cos();
  156. }
  157. });
  158. _meths.put("sin", new DirectNativeMethod("sin") {
  159. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  160. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  161. checkArity(args, 0);
  162. return self.base_sin();
  163. }
  164. });
  165. _meths.put("tan", new DirectNativeMethod("tan") {
  166. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  167. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  168. checkArity(args, 0);
  169. return self.base_tan();
  170. }
  171. });
  172. _meths.put("log", new DirectNativeMethod("log") {
  173. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  174. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  175. checkArity(args, 0);
  176. return self.base_log();
  177. }
  178. });
  179. _meths.put("sqrt", new DirectNativeMethod("sqrt") {
  180. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  181. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  182. checkArity(args, 0);
  183. return self.base_sqrt();
  184. }
  185. });
  186. _meths.put("expt", new DirectNativeMethod("expt") {
  187. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  188. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  189. checkArity(args, 1);
  190. NATNumeric pow = get(args, 1).asNativeNumeric();
  191. return self.base_expt(pow);
  192. }
  193. });
  194. _meths.put("<", new DirectNativeMethod("<") {
  195. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  196. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  197. checkArity(args, 1);
  198. NATNumeric other = get(args, 1).asNativeNumeric();
  199. return self.base__opltx_(other);
  200. }
  201. });
  202. _meths.put(">", new DirectNativeMethod(">") {
  203. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  204. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  205. checkArity(args, 1);
  206. NATNumeric other = get(args, 1).asNativeNumeric();
  207. return self.base__opgtx_(other);
  208. }
  209. });
  210. _meths.put("<=", new DirectNativeMethod("<=") {
  211. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  212. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  213. checkArity(args, 1);
  214. NATNumeric other = get(args, 1).asNativeNumeric();
  215. return self.base__opltx__opeql_(other);
  216. }
  217. });
  218. _meths.put(">=", new DirectNativeMethod(">=") {
  219. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  220. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  221. checkArity(args, 1);
  222. NATNumeric other = get(args, 1).asNativeNumeric();
  223. return self.base__opgtx__opeql_(other);
  224. }
  225. });
  226. _meths.put("=", new DirectNativeMethod("=") {
  227. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  228. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  229. checkArity(args, 1);
  230. NATNumeric other = get(args, 1).asNativeNumeric();
  231. return self.base__opeql_(other);
  232. }
  233. });
  234. _meths.put("!=", new DirectNativeMethod("!=") {
  235. public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
  236. NATNumeric self = ctx.base_receiver().asNativeNumeric();
  237. checkArity(args, 1);
  238. return self.base__opnot__opeql_(get(args, 1));
  239. }
  240. });
  241. }
  242. /**
  243. * Overrides the default AmbientTalk native object behavior of extracting native
  244. * methods based on the 'base_' naming convention. Instead, native AT numbers use
  245. * an explicit hashmap of native methods. This is much faster than the default
  246. * behavior, which requires reflection.
  247. */
  248. protected boolean hasLocalMethod(ATSymbol atSelector) throws InterpreterException {
  249. if (_meths.containsKey(atSelector.base_text().asNativeText().javaValue)) {
  250. return true;
  251. } else {
  252. return super.hasLocalMethod(atSelector);
  253. }
  254. }
  255. /**
  256. * @see NATNumeric#hasLocalMethod(ATSymbol)
  257. */
  258. protected ATMethod getLocalMethod(ATSymbol selector) throws InterpreterException {
  259. ATMethod val = _meths.get(selector.base_text().asNativeText().javaValue);
  260. if (val == null) {
  261. return super.getLocalMethod(selector);
  262. //throw new XSelectorNotFound(selector, this);
  263. }
  264. return val;
  265. }
  266. }