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