/interpreter/tags/at2dist130208/src/edu/vub/at/objects/mirrors/NATMirage.java
Java | 542 lines | 353 code | 88 blank | 101 comment | 6 complexity | 8cee05320baf61c81b07d6e3a0287fc2 MD5 | raw file
1/** 2 * AmbientTalk/2 Project 3 * NATMirage.java created on Oct 2, 2006 at 10:08:12 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.exceptions.InterpreterException; 32import edu.vub.at.exceptions.XIllegalArgument; 33import edu.vub.at.exceptions.XTypeMismatch; 34import edu.vub.at.objects.ATBoolean; 35import edu.vub.at.objects.ATClosure; 36import edu.vub.at.objects.ATContext; 37import edu.vub.at.objects.ATField; 38import edu.vub.at.objects.ATMethod; 39import edu.vub.at.objects.ATNil; 40import edu.vub.at.objects.ATObject; 41import edu.vub.at.objects.ATTypeTag; 42import edu.vub.at.objects.ATTable; 43import edu.vub.at.objects.coercion.NativeTypeTags; 44import edu.vub.at.objects.grammar.ATAssignmentSymbol; 45import edu.vub.at.objects.grammar.ATSymbol; 46import edu.vub.at.objects.natives.FieldMap; 47import edu.vub.at.objects.natives.MethodDictionary; 48import edu.vub.at.objects.natives.NATCallframe; 49import edu.vub.at.objects.natives.OBJNil; 50import edu.vub.at.objects.natives.NATObject; 51import edu.vub.at.objects.natives.NATTable; 52import edu.vub.at.objects.natives.NATText; 53import edu.vub.at.objects.natives.grammar.AGSymbol; 54 55import java.util.LinkedList; 56import java.util.Vector; 57 58/** 59 * A NATMirage is an object that forwards all meta-operations invoked upon it (at 60 * the java-level) to its designated mirror object. To cut off infinite meta-regress 61 * it also has magic_ variants of them which delegate to the default implementation. 62 * 63 * @author smostinc 64 */ 65public class NATMirage extends NATObject { 66 67 // Whenever this field is set, the object should be tested for the _MIRROR_ native type tag 68 private ATObject mirror_; 69 70 public static NATMirage createMirage(ATClosure code, ATObject dynamicParent, boolean parentType, ATTypeTag[] types, ATObject mirror) throws InterpreterException { 71 if (mirror.meta_isTaggedAs(NativeTypeTags._MIRROR_).asNativeBoolean().javaValue) { 72 // create a new, uninitialized mirage 73 NATMirage newMirage = new NATMirage(dynamicParent, code.base_context().base_lexicalScope(), parentType, types); 74 75 // create a new instance of the mirror with the uninitialized mirage, this implicitly clones 76 // the mirror and re-initializes it, setting the base field to this new mirage 77 // def mirrorClone := mirror.new(<uninitialized mirage>) 78 // the init method of the mirror root will normally 79 ATObject mirrorClone = mirror.meta_invoke(mirror, NATObject._NEW_NAME_, NATTable.of(newMirage)); 80 81 // set the mirage's mirror to the cloned mirror 82 newMirage.initializeWithMirror(mirrorClone); 83 return newMirage; 84 } else { 85 throw new XIllegalArgument("Object used as a mirror without having the Mirror type tag: " + mirror); 86 } 87 } 88 89 /** 90 * Dedicated constructor for creating the initial empty mirage tied to the mirror root prototype. 91 */ 92 protected NATMirage(NATMirrorRoot mirror) { 93 super(); 94 mirror_ = mirror; 95 } 96 97 public NATMirage(ATObject dynamicParent, ATObject lexParent, boolean parentType, ATTypeTag[] types) { 98 super(dynamicParent, lexParent, parentType, types); 99 mirror_ = OBJNil._INSTANCE_; // set to nil while not initialized 100 } 101 102 /** 103 * Private setter to be used in OBJMirrorRoot.init to break the chicken-and-egg cycle when 104 * having to create both a mirror and its mirage simultaneously. The sequence is as follows: 105 * 1) a new empty 'uninitialized' mirage is created, with mirror as nil 106 * 2) a mirror is instantiated, leading to the invocation of its init method 107 * 3) the initialization of a new OBJMirrorRoot assigns the uninitialized mirage to its 'base' field 108 * 4) the mirror field of the uninitialized mirage is set to the newly created mirror, using this method. 109 */ 110 private void initializeWithMirror(ATObject realMirror) { 111 mirror_ = realMirror; 112 } 113 114 /** 115 * Constructs a new ambienttalk mirage as a clone of an existing one. This results in a new 116 * uninitialized mirage (i.e. a mirage whose mirror points to nil). The code that clones the 117 * mirage must ensure that the mirror is correctly bound to a new instance of the cloned mirage's mirror. 118 119 * 120 * 121 */ 122 protected NATMirage(FieldMap map, 123 Vector state, 124 LinkedList customFields, 125 MethodDictionary methodDict, 126 ATObject dynamicParent, 127 ATObject lexicalParent, 128 byte flags, 129 ATTypeTag[] types) throws InterpreterException { 130 super(map, state, customFields, methodDict, dynamicParent, lexicalParent, flags, types); 131 mirror_ = OBJNil._INSTANCE_; 132 } 133 134 public NATMirage asMirage() throws XTypeMismatch { 135 return this; 136 } 137 138 // Called by the default NATObject Cloning algorithm 139 protected NATObject createClone(FieldMap map, 140 Vector state, 141 LinkedList customFields, 142 MethodDictionary methodDict, 143 ATObject dynamicParent, 144 ATObject lexicalParent, 145 byte flags, ATTypeTag[] types) throws InterpreterException { 146 NATMirage clonedMirage = new NATMirage(map, 147 state, 148 customFields, 149 methodDict, 150 dynamicParent, 151 lexicalParent, 152 flags, 153 types); 154 // clonedMirage.mirror := myMirror.new(clonedMirage) 155 clonedMirage.mirror_ = mirror_.meta_invoke(mirror_, NATObject._NEW_NAME_, NATTable.of(clonedMirage)); 156 return clonedMirage; 157 } 158 159 /** 160 * Access to the mirage's mirror, to enable a mirage to be 'upped' to a mirror value. 161 */ 162 protected ATObject getMirror() { 163 return mirror_; 164 } 165 166 // MAGIC METHODS 167 // Cut-off for infinite meta-regress 168 169 public ATNil magic_addMethod(ATMethod method) throws InterpreterException { 170 return super.meta_addMethod(method); 171 } 172 173 public ATObject magic_clone() throws InterpreterException { 174 return super.meta_clone(); 175 } 176 177 public ATNil magic_defineField(ATSymbol name, ATObject value) throws InterpreterException { 178 return super.meta_defineField(name, value); 179 } 180 181 public ATMethod magic_grabMethod(ATSymbol selector) throws InterpreterException { 182 return super.meta_grabMethod(selector); 183 } 184 185 /** 186 * <tt>invoke</tt> deviates from the default super-calling behaviour because 187 * the inherited <tt>invoke</tt> implementation from {@link NATCallframe} 188 * performs a self-send to {@link this#impl_selectAccessor(ATObject, ATSymbol)} 189 * or {@link this#impl_selectMutator(ATObject, ATAssignmentSymbol)}. However, 190 * these methods are overridden in the mirage to transform the impl methods into 191 * <tt>invoke</tt> methods, which causes an infinite loop. 192 * To break the loop, the inherited implementation is duplicated here, and the 193 * self-sends are replaced by static super-sends, such that the native implementation 194 * of the impl methods can be reused. 195 */ 196 public ATObject magic_invoke(ATObject receiver, ATSymbol selector, ATTable arguments) throws InterpreterException { 197 //return super.meta_invoke(receiver, selector, arguments); 198 // If the selector is an assignment symbol (i.e. `field:=) try to assign the corresponding field 199 if (selector.isAssignmentSymbol()) { 200 return super.impl_invokeMutator(receiver, selector.asAssignmentSymbol(), arguments); 201 } else { 202 return super.impl_invokeAccessor(receiver, selector, arguments); 203 } 204 } 205 206 public ATTable magic_listMethods() throws InterpreterException { 207 return super.meta_listMethods(); 208 } 209 210 public ATObject magic_newInstance(ATTable initargs) throws InterpreterException { 211 return super.meta_newInstance(initargs); 212 } 213 214 public NATText magic_print() throws InterpreterException { 215 return super.meta_print(); 216 } 217 218 public ATObject magic_receive(ATAsyncMessage message) throws InterpreterException { 219 return super.meta_receive(message); 220 } 221 222 public ATBoolean magic_respondsTo(ATSymbol selector) throws InterpreterException { 223 return super.meta_respondsTo(selector); 224 } 225 226 /** 227 * <tt>select</tt> deviates from the default super-calling behaviour because 228 * the inherited <tt>select</tt> implementation from {@link NATCallframe} 229 * performs a self-send to {@link this#impl_selectAccessor(ATObject, ATSymbol)} 230 * or {@link this#impl_selectMutator(ATObject, ATAssignmentSymbol)}. However, 231 * these methods are overridden in the mirage to transform the impl methods into 232 * <tt>select</tt> methods, which causes an infinite loop. 233 * To break the loop, the inherited implementation is duplicated here, and the 234 * self-sends are replaced by static super-sends, such that the native implementation 235 * of the impl methods can be reused. 236 */ 237 public ATObject magic_select(ATObject receiver, ATSymbol selector) throws InterpreterException { 238 //return super.meta_select(receiver, selector); 239 if (selector.isAssignmentSymbol()) { 240 return super.impl_selectMutator(receiver, selector.asAssignmentSymbol()); 241 } else { 242 return super.impl_selectAccessor(receiver, selector); 243 } 244 } 245 246 public ATNil magic_addField(ATField field) throws InterpreterException { 247 return super.meta_addField(field); 248 } 249 250 251 public ATObject magic_doesNotUnderstand(ATSymbol selector) throws InterpreterException { 252 return super.meta_doesNotUnderstand(selector); 253 } 254 255 256 public ATField magic_grabField(ATSymbol selector) throws InterpreterException { 257 return super.meta_grabField(selector); 258 } 259 260 261 public ATTable magic_listFields() throws InterpreterException { 262 return super.meta_listFields(); 263 } 264 265 266 public ATObject magic_send(ATObject receiver, ATAsyncMessage message) throws InterpreterException { 267 return super.meta_send(receiver, message); 268 } 269 270 271 public ATObject magic_eval(ATContext ctx) throws InterpreterException { 272 return super.meta_eval(ctx); 273 } 274 275 276 public ATObject magic_quote(ATContext ctx) throws InterpreterException { 277 return super.meta_quote(ctx); 278 } 279 280 public ATBoolean magic_isExtensionOfParent() throws InterpreterException { 281 return super.meta_isExtensionOfParent(); 282 } 283 284 public ATObject magic_invokeField(ATObject rcv, ATSymbol sym) throws InterpreterException { 285 return super.meta_invokeField(rcv, sym); 286 } 287 288 public ATObject magic_pass() throws InterpreterException { 289 return super.meta_pass(); 290 } 291 292 public ATObject magic_resolve() throws InterpreterException { 293 return super.meta_resolve(); 294 } 295 296 public ATBoolean magic_isTaggedAs(ATTypeTag type) throws InterpreterException { 297 return super.meta_isTaggedAs(type); 298 } 299 300 public ATTable magic_typeTags() throws InterpreterException { 301 return super.meta_typeTags(); 302 } 303 304 public ATBoolean magic_isCloneOf(ATObject original) throws InterpreterException { 305 return super.meta_isCloneOf(original); 306 } 307 308 public ATBoolean magic_isRelatedTo(ATObject object) throws InterpreterException { 309 return super.meta_isRelatedTo(object); 310 } 311 312 /* ======================================================================== 313 * Each meta_x method defined in ATObject is implemented in a mirage as a 314 * forwarding method that asks its mirror to perform the operation on itself 315 * instead. 316 * ======================================================================== */ 317 318 public ATNil meta_addMethod(ATMethod method) throws InterpreterException { 319 mirror_.meta_invoke( 320 mirror_, 321 AGSymbol.jAlloc("addMethod"), 322 NATTable.atValue(new ATObject[] { method }) 323 ); 324 325 return OBJNil._INSTANCE_; 326 } 327 328 public ATObject meta_clone() throws InterpreterException { 329 return mirror_.meta_invoke( 330 mirror_, 331 AGSymbol.jAlloc("clone"), 332 NATTable.EMPTY); 333 } 334 335 public ATNil meta_defineField(ATSymbol name, ATObject value) throws InterpreterException { 336 mirror_.meta_invoke( 337 mirror_, 338 AGSymbol.jAlloc("defineField"), 339 NATTable.atValue(new ATObject[] { name, value })); 340 return OBJNil._INSTANCE_; 341 } 342 343 public ATMethod meta_grabMethod(ATSymbol selector) throws InterpreterException { 344 return mirror_.meta_invoke( 345 mirror_, 346 AGSymbol.jAlloc("grabMethod"), 347 NATTable.atValue(new ATObject[] { selector }) 348 ).asMethod(); 349 } 350 351 public ATObject meta_invoke(ATObject receiver, ATSymbol selector, ATTable arguments) throws InterpreterException { 352 return mirror_.meta_invoke( 353 mirror_, 354 AGSymbol.jAlloc("invoke"), 355 NATTable.atValue(new ATObject[] { receiver, selector, arguments })); 356 } 357 358 public ATTable meta_listMethods() throws InterpreterException { 359 return mirror_.meta_invoke( 360 mirror_, 361 AGSymbol.jAlloc("listMethods"), 362 NATTable.EMPTY 363 ).asTable(); 364 } 365 366 public ATObject meta_newInstance(ATTable initargs) throws InterpreterException { 367 return mirror_.meta_invoke( 368 mirror_, 369 AGSymbol.jAlloc("newInstance"), 370 NATTable.atValue(new ATObject[] { initargs })); 371 } 372 373 public NATText meta_print() throws InterpreterException { 374 return mirror_.meta_invoke( 375 mirror_, 376 AGSymbol.jAlloc("print"), 377 NATTable.EMPTY).asNativeText(); 378 } 379 380 public ATObject meta_receive(ATAsyncMessage message) throws InterpreterException { 381 return mirror_.meta_invoke( 382 mirror_, 383 AGSymbol.jAlloc("receive"), 384 NATTable.atValue(new ATObject[] { message })); 385 } 386 387 public ATBoolean meta_respondsTo(ATSymbol selector) throws InterpreterException { 388 return mirror_.meta_invoke( 389 mirror_, 390 AGSymbol.jAlloc("respondsTo"), 391 NATTable.atValue(new ATObject[] { selector }) 392 ).asBoolean(); 393 } 394 395 public ATClosure meta_select(ATObject receiver, ATSymbol selector) throws InterpreterException { 396 return mirror_.meta_invoke( 397 mirror_, 398 AGSymbol.jAlloc("select"), 399 NATTable.atValue(new ATObject[] { receiver, selector })).asClosure(); 400 } 401 402 public ATNil meta_addField(ATField field) throws InterpreterException { 403 mirror_.meta_invoke( 404 mirror_, 405 AGSymbol.jAlloc("addField"), 406 NATTable.atValue(new ATObject[] { field })); 407 return OBJNil._INSTANCE_; 408 } 409 410 411 public ATClosure meta_doesNotUnderstand(ATSymbol selector) throws InterpreterException { 412 return mirror_.meta_invoke( 413 mirror_, 414 AGSymbol.jAlloc("doesNotUnderstand"), 415 NATTable.atValue(new ATObject[] { selector })).asClosure(); 416 } 417 418 419 public ATField meta_grabField(ATSymbol selector) throws InterpreterException { 420 return mirror_.meta_invoke( 421 mirror_, 422 AGSymbol.jAlloc("grabField"), 423 NATTable.atValue(new ATObject[] { selector })).asField(); 424 } 425 426 427 public ATTable meta_listFields() throws InterpreterException { 428 return mirror_.meta_invoke( 429 mirror_, 430 AGSymbol.jAlloc("listFields"), 431 NATTable.EMPTY).asTable(); 432 } 433 434 435 public ATObject meta_send(ATObject receiver, ATAsyncMessage message) throws InterpreterException { 436 return mirror_.meta_invoke( 437 mirror_, 438 AGSymbol.jAlloc("send"), 439 NATTable.atValue(new ATObject[] { receiver, message })); 440 } 441 442 443 public ATObject meta_eval(ATContext ctx) throws InterpreterException { 444 return mirror_.meta_invoke( 445 mirror_, 446 AGSymbol.jAlloc("eval"), 447 NATTable.atValue(new ATObject[] { ctx })); 448 } 449 450 451 public ATObject meta_quote(ATContext ctx) throws InterpreterException { 452 return mirror_.meta_invoke( 453 mirror_, 454 AGSymbol.jAlloc("quote"), 455 NATTable.atValue(new ATObject[] { ctx })); 456 } 457 458 public ATBoolean meta_isExtensionOfParent() throws InterpreterException { 459 return mirror_.meta_invoke( 460 mirror_, 461 AGSymbol.jAlloc("isExtensionOfParent"), 462 NATTable.EMPTY).asBoolean(); 463 } 464 465 public ATObject meta_invokeField(ATObject rcv, ATSymbol sym) throws InterpreterException { 466 return mirror_.meta_invoke( 467 mirror_, 468 AGSymbol.jAlloc("invokeField"), 469 NATTable.atValue(new ATObject[] { rcv, sym })); 470 } 471 472 public ATObject meta_pass() throws InterpreterException { 473 return mirror_.meta_invoke( 474 mirror_, AGSymbol.jAlloc("pass"), NATTable.EMPTY); 475 } 476 477 public ATObject meta_resolve() throws InterpreterException { 478 return mirror_.meta_invoke( 479 mirror_, AGSymbol.jAlloc("resolve"), NATTable.EMPTY); 480 } 481 482 public ATBoolean meta_isTaggedAs(ATTypeTag type) throws InterpreterException { 483 return mirror_.meta_invoke( 484 mirror_, AGSymbol.jAlloc("isTaggedAs"), NATTable.of(type)).asBoolean(); 485 } 486 487 public ATTable meta_typeTags() throws InterpreterException { 488 return mirror_.meta_invoke( 489 mirror_, 490 AGSymbol.jAlloc("typeTags"), 491 NATTable.EMPTY).asTable(); 492 } 493 494 public ATBoolean meta_isCloneOf(ATObject original) throws InterpreterException { 495 return mirror_.meta_invoke( 496 mirror_, 497 AGSymbol.jAlloc("isCloneOf"), 498 NATTable.atValue(new ATObject[] { original })).asBoolean(); 499 } 500 501 public ATBoolean meta_isRelatedTo(ATObject object) throws InterpreterException { 502 return mirror_.meta_invoke( 503 mirror_, 504 AGSymbol.jAlloc("isRelatedTo"), 505 NATTable.atValue(new ATObject[] { object })).asBoolean(); 506 } 507 508 /** implementation-level method is mapped onto regular MOP method */ 509 public ATObject impl_invokeAccessor(ATObject receiver, ATSymbol selector, ATTable arguments) throws InterpreterException { 510 return mirror_.meta_invoke( 511 mirror_, 512 AGSymbol.jAlloc("invoke"), 513 NATTable.atValue(new ATObject[] { receiver, selector, arguments })); 514 } 515 516 /** implementation-level method is mapped onto regular MOP method */ 517 public ATObject impl_invokeMutator(ATObject receiver, ATAssignmentSymbol selector, ATTable arguments) throws InterpreterException { 518 return mirror_.meta_invoke( 519 mirror_, 520 AGSymbol.jAlloc("invoke"), 521 NATTable.atValue(new ATObject[] { receiver, selector, arguments })); 522 } 523 524 /** implementation-level method is mapped onto regular MOP method */ 525 public ATClosure impl_selectAccessor(ATObject receiver, ATSymbol selector) throws InterpreterException { 526 return mirror_.meta_invoke( 527 mirror_, 528 AGSymbol.jAlloc("select"), 529 NATTable.atValue(new ATObject[] { receiver, selector })).asClosure(); 530 } 531 532 /** implementation-level method is mapped onto regular MOP method */ 533 public ATClosure impl_selectMutator(ATObject receiver, ATAssignmentSymbol selector) throws InterpreterException { 534 return mirror_.meta_invoke( 535 mirror_, 536 AGSymbol.jAlloc("select"), 537 NATTable.atValue(new ATObject[] { receiver, selector })).asClosure(); 538 } 539 540 541 542}