/interpreter/tags/reactive-pattern-matching/src/edu/vub/at/objects/mirrors/NATIntrospectiveMirror.java

http://ambienttalk.googlecode.com/ · Java · 241 lines · 85 code · 24 blank · 132 comment · 6 complexity · 1e741c27b7e57663df4d240556978648 MD5 · raw file

  1. /**
  2. * AmbientTalk/2 Project
  3. * NATMirror.java created on Aug 13, 2006 at 10:09:29 AM
  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.mirrors;
  29. import edu.vub.at.exceptions.InterpreterException;
  30. import edu.vub.at.exceptions.XArityMismatch;
  31. import edu.vub.at.exceptions.XSelectorNotFound;
  32. import edu.vub.at.exceptions.XTypeMismatch;
  33. import edu.vub.at.objects.ATBoolean;
  34. import edu.vub.at.objects.ATMethod;
  35. import edu.vub.at.objects.ATObject;
  36. import edu.vub.at.objects.ATTable;
  37. import edu.vub.at.objects.coercion.NativeTypeTags;
  38. import edu.vub.at.objects.grammar.ATSymbol;
  39. import edu.vub.at.objects.natives.NATBoolean;
  40. import edu.vub.at.objects.natives.NATByRef;
  41. import edu.vub.at.objects.natives.NATNumber;
  42. import edu.vub.at.objects.natives.NATTable;
  43. import edu.vub.at.objects.natives.NATText;
  44. /**
  45. * <p>NATIntrospectiveMirror is a default mirror to represent an ambienttalk object
  46. * which is capable of offering the java meta-interface of any language value at the
  47. * ambienttalk level. This allows introspection into the language value's internals
  48. * as well as invoking some meta-level operations on it. Technically, NATMirror is
  49. * simply a wrapper object around an ambienttalk object which deifies (ups) methods
  50. * invoked upon it.</p>
  51. *
  52. * <p>Note that whereas the mirror can offer e.g. an apply method when reifying a
  53. * closure, this does not affect its own meta-interface. A NATMirror is always an
  54. * object and can thus not be applied at the ambienttalk level.</p>
  55. *
  56. * Example:
  57. * <pre>
  58. * def clo := { | x | x * 2 };
  59. * def m := at.mirrors.Factory.createMirror(clo);
  60. *
  61. * clo( 5 ) <i> => 10 (legal) </i>
  62. * m.apply([5]) <i> => 10 (legal) </i>
  63. * m( 5 ) <i> => error (Application expected a closure, given a mirror) </i>
  64. * </pre>
  65. *
  66. * @author smostinc
  67. * @author tvcutsem
  68. */
  69. public class NATIntrospectiveMirror extends NATByRef {
  70. /** the object reflected on. This object is NOT a NATMirage */
  71. private final ATObject principal_;
  72. /**
  73. * Return a mirror on the given native or custom AmbientTalk object.
  74. *
  75. * @param objectRepresentation the object to reflect upon
  76. * @return either an introspective mirror (if the passed object is native), otherwise
  77. * a custom intercessive mirror.
  78. */
  79. public static final ATObject atValue(ATObject objectRepresentation) throws XTypeMismatch {
  80. if (objectRepresentation.isMirage()) {
  81. return objectRepresentation.asMirage().getMirror();
  82. } else {
  83. return new NATIntrospectiveMirror(objectRepresentation);
  84. }
  85. }
  86. /**
  87. * An introspective mirror is a wrapper which forwards a deified (upped) version of invoked
  88. * methods and field accesses to its principal. This principal is a Java object
  89. * representing an ambienttalk object. The deificiation process implies that
  90. * only the object's meta_level operations (implemented in Java) will be called
  91. * directly by the mirror.
  92. *
  93. * @param representation - the object to reflect upon, which is *not* a NATMirage
  94. */
  95. private NATIntrospectiveMirror(ATObject representation) {
  96. principal_ = representation;
  97. }
  98. public NATIntrospectiveMirror asNativeIntrospectiveMirror() {
  99. return this;
  100. }
  101. public boolean isNativeIntrospectiveMirror() {
  102. return true;
  103. }
  104. /**
  105. * This method is used to allow selecting the base field of an intercessive mirror using
  106. * the reflective selection of fields. This method is never invoked directly by the
  107. * implementation.
  108. * @return the base-level entity this mirror reflects on
  109. */
  110. public ATObject base_base() {
  111. return principal_;
  112. }
  113. public int hashCode() { return principal_.hashCode(); }
  114. public ATBoolean base__opeql__opeql_(ATObject other) throws InterpreterException {
  115. if (other.isNativeIntrospectiveMirror()) {
  116. return principal_.base__opeql__opeql_(other.asNativeIntrospectiveMirror().principal_);
  117. } else {
  118. return NATBoolean._FALSE_;
  119. }
  120. }
  121. /* ------------------------------------------
  122. * -- Slot accessing and mutating protocol --
  123. * ------------------------------------------ */
  124. public ATMethod meta_grabMethod(ATSymbol methodName) throws InterpreterException {
  125. try {
  126. // try to find a meta_ method in the principal
  127. return Reflection.downMetaLevelMethod(principal_, methodName);
  128. } catch (XSelectorNotFound e) {
  129. e.catchOnlyIfSelectorEquals(methodName);
  130. // try to find a base_ method in the mirror
  131. return super.meta_grabMethod(methodName);
  132. }
  133. }
  134. /**
  135. * Listing the methods of a mirror requires us to list all of the meta_ methods
  136. * of the principal + all of the base_ methods of the mirror itself
  137. */
  138. public ATTable meta_listMethods() throws InterpreterException {
  139. ATMethod[] principalMetaMethods = Reflection.downMetaLevelMethods(principal_);
  140. ATMethod[] mirrorBaseMethods = Reflection.downBaseLevelMethods(this);
  141. return NATTable.atValue(NATTable.collate(principalMetaMethods, mirrorBaseMethods));
  142. }
  143. /* ------------------------------------
  144. * -- Extension and cloning protocol --
  145. * ------------------------------------ */
  146. /**
  147. * This method allows re-initialise a mirror object. However, since the link from a
  148. * mirror to its base object is immutable, this results in contacting the mirror
  149. * factory, to create a (new) mirror for the requested object.
  150. * @param initargs an ATObject[] containing as its first element the object that needs to be reflects upon
  151. * @return <b>another</b> (possibly new) mirror object
  152. */
  153. public ATObject meta_newInstance(ATTable initargs) throws InterpreterException {
  154. int len = initargs.base_length().asNativeNumber().javaValue;
  155. if (len != 1)
  156. throw new XArityMismatch("init method of mirror", 1, len);
  157. ATObject reflectee = initargs.base_at(NATNumber.ONE);
  158. return atValue(reflectee);
  159. /*ATObject[] initargs = init.asNativeTable().elements_;
  160. if(initargs.length != 1) {
  161. ATObject reflectee = initargs[0];
  162. return atValue(reflectee);
  163. } else {
  164. throw new XArityMismatch("init", 1, initargs.length);
  165. }*/
  166. }
  167. /* ---------------------------------
  168. * -- Abstract Grammar Protocol --
  169. * --------------------------------- */
  170. public NATText meta_print() throws InterpreterException {
  171. return NATText.atValue("<mirror on:"+principal_.meta_print().javaValue+">");
  172. }
  173. public ATTable meta_typeTags() throws InterpreterException {
  174. return NATTable.of(NativeTypeTags._MIRROR_);
  175. }
  176. /**
  177. * OBSOLETE: introspective mirrors are now pass-by-reference.
  178. * This has the following repercussions:
  179. * - when passing the mirror of an isolate, a remote ref to the mirror is passed instead.
  180. * The isolate is not copied.
  181. * - mirrors on far references can still be created, by passing the principal by ref
  182. * and by reflecting on the obtained far reference
  183. *
  184. * An introspective mirror is pass-by-copy.
  185. * When an introspective mirror is deserialized, it will become a mirror on
  186. * its deserialized principal. This means that, if the principal is passed
  187. * by copy, the mirror will be a local mirror on the copy. If the principal is passed
  188. * by reference, the mirror will be a local mirror on the far reference.
  189. */
  190. /*public ATObject meta_resolve() throws InterpreterException {
  191. if(principal_ instanceof NATMirage)
  192. return ((NATMirage)principal_).getMirror();
  193. else
  194. return this;
  195. }*/
  196. /**
  197. * For mirrors, first try to find a <tt>meta_</tt> method in the principal.
  198. * If this fails, try to find a <tt>base_</tt> method in the introspective mirror itself.
  199. */
  200. protected boolean hasLocalMethod(ATSymbol atSelector) throws InterpreterException {
  201. return Reflection.upRespondsTo(principal_, Reflection.upMetaLevelSelector(atSelector)) ||
  202. super.hasLocalMethod(atSelector);
  203. }
  204. /**
  205. * For mirrors, first try to find a <tt>meta_</tt> method in the principal.
  206. * If this fails, try to find a <tt>base_</tt> method in the introspective mirror itself.
  207. */
  208. protected ATMethod getLocalMethod(ATSymbol selector) throws InterpreterException {
  209. try {
  210. String methSelector = Reflection.upMetaLevelSelector(selector);
  211. return Reflection.upMethodSelection(principal_, methSelector, selector);
  212. } catch (XSelectorNotFound e) {
  213. e.catchOnlyIfSelectorEquals(selector);
  214. return super.getLocalMethod(selector);
  215. }
  216. }
  217. }