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

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