/interpreter/tags/at2dist170907/src/edu/vub/at/objects/mirrors/NATIntrospectiveMirror.java

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