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