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