/interpreter/tags/at2dist030708/src/edu/vub/at/objects/mirrors/NATMirrorRoot.java
Java | 338 lines | 164 code | 51 blank | 123 comment | 10 complexity | c48885ee6b442c34e8918a77bbd3c43f MD5 | raw file
1/** 2 * AmbientTalk/2 Project 3 * OBJMirrorRoot.java created on Oct 3, 2006 at 3:26:08 PM 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.actors.ATAsyncMessage; 31import edu.vub.at.eval.Evaluator; 32import edu.vub.at.exceptions.InterpreterException; 33import edu.vub.at.exceptions.XArityMismatch; 34import edu.vub.at.exceptions.XIllegalArgument; 35import edu.vub.at.objects.ATBoolean; 36import edu.vub.at.objects.ATContext; 37import edu.vub.at.objects.ATField; 38import edu.vub.at.objects.ATMethod; 39import edu.vub.at.objects.ATMethodInvocation; 40import edu.vub.at.objects.ATNil; 41import edu.vub.at.objects.ATObject; 42import edu.vub.at.objects.ATTable; 43import edu.vub.at.objects.ATTypeTag; 44import edu.vub.at.objects.coercion.NativeTypeTags; 45import edu.vub.at.objects.grammar.ATSymbol; 46import edu.vub.at.objects.natives.NATByCopy; 47import edu.vub.at.objects.natives.NATTable; 48import edu.vub.at.objects.natives.NATText; 49import edu.vub.at.objects.natives.grammar.AGSymbol; 50import edu.vub.at.util.logging.Logging; 51 52import java.io.IOException; 53 54/** 55 * This class denotes the root node of the intercessive mirrors delegation hierarchy. 56 * 57 * Intercessive mirrors are always tied to a particular 'base' object. 58 * The default intercessive mirror is named 'mirrorroot' and is an object 59 * that understands all meta_* operations, implementing them using default semantics. 60 * It can be thought of as being defined as follows: 61 * 62 * def mirrorroot := object: { 63 * def base := object: { nil } mirroredBy: self // base of the mirror root is an empty mirage 64 * def init(b) { 65 * base := b 66 * } 67 * def invoke(@args) { <default native invocation behaviour on base> } 68 * def select(@args) { <default native selection behaviour on base> } 69 * ... 70 * } taggedAs: [ Mirror ] 71 * 72 * This object can then simply be extended / composed by other objects to deviate from the default semantics. 73 * Note that the default semantics is applied to 'base' and *not* 'self.base', in other words: 74 * although child mirrors can define their own 'base' field, it is not taken into consideration 75 * by the mirror root. This also ensures that the mirror root is not abused to enact upon a mirage 76 * for which it was not assigned to be the mirror. 77 * 78 * Hence, 'mirrors' are simply objects with the same interface as this mirrorroot object: they should be 79 * able to respond to all meta_* messages and have a 'base' field. 80 * 81 * @author tvcutsem, smostinc 82 */ 83public final class NATMirrorRoot extends NATByCopy implements ATObject { 84 85 // The name of the field that points to the base_level representation of a custom mirror 86 public static final AGSymbol _BASE_NAME_ = AGSymbol.jAlloc("base"); 87 88 // the native read-only 'base' field of the mirror root 89 private NATMirage base_; 90 91 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { 92 try { 93 in.defaultReadObject(); 94 } catch(IOException e) { 95 Logging.Actor_LOG.fatal("Failed to reconstruct an OBJMirrorRoot", e); 96 throw e; 97 } 98 } 99 100 /** 101 * Constructor used to initialize the initial mirror root prototype. 102 */ 103 public NATMirrorRoot() { 104 base_ = new NATMirage(this); 105 }; 106 107 /** 108 * Constructor used for cloning: creates a shallow copy of the mirror root. 109 * @param base the base field value of the original mirror root from which 110 * this new one will be cloned. 111 */ 112 private NATMirrorRoot(NATMirage base) { 113 base_ = base; 114 }; 115 116 /** 117 * OBJMirrorRoot's primitive 'init method, in pseudo-code: 118 * 119 * def init(newBase) { 120 * base := newBase 121 * } 122 */ 123 public ATObject base_init(ATObject[] initargs) throws InterpreterException { 124 if (initargs.length != 1) { 125 throw new XArityMismatch("init", 1, initargs.length); 126 } 127 128 NATMirage newBase = initargs[0].asMirage(); 129 // check whether the passed base field does not have a mirror assigned to it yet 130 if (newBase.getMirror() == Evaluator.getNil()) { 131 base_ = newBase; 132 return newBase; 133 } else { 134 throw new XIllegalArgument("mirror root's init method requires an uninitialized mirage, found: " + newBase); 135 } 136 } 137 138 /** 139 * This implementation is actually an ad hoc modification of the NATObject implementation 140 * of instance creation, dedicated for the mirror root. Using the NATObject implementation 141 * would work perfectly, but this one is more efficient. 142 */ 143 public ATObject meta_newInstance(ATTable initargs) throws InterpreterException { 144 ATObject[] initargz = initargs.asNativeTable().elements_; 145 if (initargz.length != 1) { 146 throw new XArityMismatch("newInstance", 1, initargz.length); 147 } 148 NATMirage newBase = initargz[0].asMirage(); 149 // check whether the passed base field does not have a mirror assigned to it yet 150 if (newBase.getMirror() == Evaluator.getNil()) { 151 return new NATMirrorRoot(newBase); 152 } else { 153 throw new XIllegalArgument("mirror root's init method requires an uninitialized mirage, found: " + newBase); 154 } 155 } 156 157 /* ------------------------------------ 158 * -- Extension and cloning protocol -- 159 * ------------------------------------ */ 160 161 /** 162 * The mirror root is cloned but the base field is only shallow-copied, i.e. it is shared 163 * between the clones! Normally, mirrors are instantiated rather than cloned when assigned 164 * to a new object, such that this new base field will be re-assigned to another mirage 165 * (in {@link NATMirrorRoot#base_init(ATObject[])}). 166 */ 167 public ATObject meta_clone() throws InterpreterException { 168 return new NATMirrorRoot(base_); 169 } 170 171 public ATTable meta_typeTags() throws InterpreterException { 172 return NATTable.of(NativeTypeTags._MIRROR_); 173 } 174 175 public NATText meta_print() throws InterpreterException { 176 return NATText.atValue("<mirror on: "+base_+">"); 177 } 178 179 180 /** 181 * The read-only field containing the mirror's base-level mirage. 182 */ 183 public NATMirage base_base() throws InterpreterException { 184 return base_; 185 } 186 187 188 /* ------------------------------------------ 189 * -- Slot accessing and mutating protocol -- 190 * ------------------------------------------ */ 191 192 /* 193 * <p>The effect of selecting fields or methods on a mirror (through meta_select) 194 * consists of checking whether the requested selector matches a field of the 195 * principal wrapped by this mirror. If this is the case, the principal's 196 * ('meta_get' + selector) method will be invoked. Else the selector might 197 * identify one of the principal's meta-operations. If this is the case, then 198 * an AmbientTalk representation of the Java method ('meta_' + selector) will 199 * be returned. </p> 200 * 201 * <p>Because an explicit AmbientTalk method invocation must be converted into 202 * an implicit Java method invocation, the invocation must be deified ('upped'). 203 * To uphold stratification of the mirror architecture, the result of this 204 * operation should be a mirror on the result of the Java method invocation.</p> 205 * 206 * <p>Note that only when the principal does not have a matching meta_level field 207 * or method the mirror itself will be tested for a corresponding base_level 208 * behaviour (e.g. for its base field or for operators such as ==). In the 209 * latter case, stratification is not enforced. This is due to the fact that 210 * the said fields and methods are not meta-level behaviour, rather they are 211 * base-level operations which happen to be applicable on a mirror. An added 212 * advantage of this technique is that it permits a mirror to have a field 213 * referring to its principal.</p> 214 */ 215 216 /* ======================================================================== 217 * OBJMirrorRoot has a base_x method for each meta_x method defined in ATObject. 218 * Each base_x method invokes NATObject's default behaviour on the base_ NATMirage 219 * via that mirage's magic_x methods. 220 * ======================================================================== */ 221 222 public ATObject base_clone() throws InterpreterException { 223 return base_base().magic_clone(); 224 } 225 226 public ATTable base_typeTags() throws InterpreterException { 227 return base_base().magic_typeTags(); 228 } 229 230 public NATText base_print() throws InterpreterException { 231 return base_base().magic_print(); 232 } 233 234 public ATObject base_pass() throws InterpreterException { 235 return base_base().magic_pass(); 236 } 237 238 public ATObject base_resolve() throws InterpreterException { 239 return base_base().magic_resolve(); 240 } 241 242 public ATNil base_addField(ATField field) throws InterpreterException { 243 return base_base().magic_addField(field); 244 } 245 246 public ATNil base_addMethod(ATMethod method) throws InterpreterException { 247 return base_base().magic_addMethod(method); 248 } 249 250 public ATNil base_addSlot(ATMethod slot) throws InterpreterException { 251 return base_base().magic_addSlot(slot); 252 } 253 254 public ATNil base_defineField(ATSymbol name, ATObject value) throws InterpreterException { 255 return base_base().magic_defineField(name, value); 256 } 257 258 public ATObject base_doesNotUnderstand(ATSymbol selector) throws InterpreterException { 259 return base_base().magic_doesNotUnderstand(selector); 260 } 261 262 public ATObject base_eval(ATContext ctx) throws InterpreterException { 263 return base_base().magic_eval(ctx); 264 } 265 266 public ATBoolean base_isExtensionOfParent() throws InterpreterException { 267 return base_base().magic_isExtensionOfParent(); 268 } 269 270 public ATObject base_invokeField(ATObject rcv, ATSymbol sym) throws InterpreterException { 271 return base_base().magic_invokeField(rcv, sym); 272 } 273 274 public ATField base_grabField(ATSymbol fieldName) throws InterpreterException { 275 return base_base().magic_grabField(fieldName); 276 } 277 278 public ATMethod base_grabMethod(ATSymbol methodName) throws InterpreterException { 279 return base_base().magic_grabMethod(methodName); 280 } 281 282 public ATMethod base_grabSlot(ATSymbol methodName) throws InterpreterException { 283 return base_base().magic_grabSlot(methodName); 284 } 285 286 public ATObject base_invoke(ATObject receiver, ATMethodInvocation inv) throws InterpreterException { 287 return base_base().magic_invoke(receiver, inv); 288 } 289 290 public ATBoolean base_isCloneOf(ATObject original) throws InterpreterException { 291 return base_base().magic_isCloneOf(original); 292 } 293 294 public ATBoolean base_isRelatedTo(ATObject object) throws InterpreterException { 295 return base_base().magic_isRelatedTo(object); 296 } 297 298 public ATBoolean base_isTaggedAs(ATTypeTag type) throws InterpreterException { 299 return base_base().magic_isTaggedAs(type); 300 } 301 302 public ATTable base_listFields() throws InterpreterException { 303 return base_base().magic_listFields(); 304 } 305 306 public ATTable base_listMethods() throws InterpreterException { 307 return base_base().magic_listMethods(); 308 } 309 310 public ATTable base_listSlots() throws InterpreterException { 311 return base_base().magic_listSlots(); 312 } 313 314 public ATObject base_newInstance(ATTable initargs) throws InterpreterException { 315 return base_base().magic_newInstance(initargs); 316 } 317 318 public ATObject base_quote(ATContext ctx) throws InterpreterException { 319 return base_base().magic_quote(ctx); 320 } 321 322 public ATObject base_receive(ATAsyncMessage message) throws InterpreterException { 323 return base_base().magic_receive(message); 324 } 325 326 public ATBoolean base_respondsTo(ATSymbol atSelector) throws InterpreterException { 327 return base_base().magic_respondsTo(atSelector); 328 } 329 330 public ATObject base_select(ATObject receiver, ATSymbol selector) throws InterpreterException { 331 return base_base().magic_select(receiver, selector); 332 } 333 334 public ATObject base_send(ATObject receiver, ATAsyncMessage message) throws InterpreterException { 335 return base_base().magic_send(receiver, message); 336 } 337 338}