PageRenderTime 68ms CodeModel.GetById 19ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 1ms

/interpreter/tags/at2dist030708/src/edu/vub/at/objects/natives/NativeATObject.java

http://ambienttalk.googlecode.com/
Java | 1017 lines | 577 code | 130 blank | 310 comment | 67 complexity | e86f668004545e3e197cc64bb1b3e3af MD5 | raw file
   1/**
   2 * AmbientTalk/2 Project
   3 * NATNil.java created on Jul 13, 2006 at 9:38:51 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.natives;
  29
  30import java.io.InvalidObjectException;
  31import java.io.ObjectStreamException;
  32import java.io.Serializable;
  33
  34import edu.vub.at.actors.ATActorMirror;
  35import edu.vub.at.actors.ATAsyncMessage;
  36import edu.vub.at.actors.ATFarReference;
  37import edu.vub.at.actors.ATLetter;
  38import edu.vub.at.actors.natives.ELActor;
  39import edu.vub.at.actors.natives.NATFarReference;
  40import edu.vub.at.actors.net.SerializationException;
  41import edu.vub.at.eval.Evaluator;
  42import edu.vub.at.eval.Import.DelegateMethod;
  43import edu.vub.at.exceptions.InterpreterException;
  44import edu.vub.at.exceptions.XIllegalOperation;
  45import edu.vub.at.exceptions.XSelectorNotFound;
  46import edu.vub.at.exceptions.XTypeMismatch;
  47import edu.vub.at.objects.ATBoolean;
  48import edu.vub.at.objects.ATClosure;
  49import edu.vub.at.objects.ATContext;
  50import edu.vub.at.objects.ATField;
  51import edu.vub.at.objects.ATHandler;
  52import edu.vub.at.objects.ATMessage;
  53import edu.vub.at.objects.ATMethod;
  54import edu.vub.at.objects.ATMethodInvocation;
  55import edu.vub.at.objects.ATNil;
  56import edu.vub.at.objects.ATNumber;
  57import edu.vub.at.objects.ATObject;
  58import edu.vub.at.objects.ATTable;
  59import edu.vub.at.objects.ATTypeTag;
  60import edu.vub.at.objects.coercion.NativeTypeTags;
  61import edu.vub.at.objects.grammar.ATAssignVariable;
  62import edu.vub.at.objects.grammar.ATAssignmentSymbol;
  63import edu.vub.at.objects.grammar.ATBegin;
  64import edu.vub.at.objects.grammar.ATDefinition;
  65import edu.vub.at.objects.grammar.ATExpression;
  66import edu.vub.at.objects.grammar.ATMessageCreation;
  67import edu.vub.at.objects.grammar.ATQuote;
  68import edu.vub.at.objects.grammar.ATSplice;
  69import edu.vub.at.objects.grammar.ATStatement;
  70import edu.vub.at.objects.grammar.ATSymbol;
  71import edu.vub.at.objects.grammar.ATUnquoteSplice;
  72import edu.vub.at.objects.mirrors.NATIntrospectiveMirror;
  73import edu.vub.at.objects.mirrors.NATMirage;
  74import edu.vub.at.objects.mirrors.NativeClosure;
  75import edu.vub.at.objects.mirrors.Reflection;
  76import edu.vub.at.objects.natives.grammar.AGAssignmentSymbol;
  77import edu.vub.at.objects.natives.grammar.AGSymbol;
  78import edu.vub.at.objects.symbiosis.JavaClass;
  79import edu.vub.at.objects.symbiosis.JavaMethod;
  80import edu.vub.at.objects.symbiosis.JavaObject;
  81import edu.vub.at.util.logging.Logging;
  82
  83/**
  84 * This class implements default semantics for all test and conversion methods.
  85 * It also implements the default metaobject protocol semantics for native
  86 * AmbientTalk objects.
  87 * <p>
  88 * More specifically, this class encapsulates the behavior for:
  89 * <ul>
  90 *  <li>The behavior of all native objects.
  91 *  <li>The default behavior of all non-native objects.
  92 * </ul>
  93 * Native AmbientTalk objects contain no fields, only methods. Fields are represented
  94 * using accessor methods. Mutable fields also have a mutator method.
  95 * <p>
  96 * To allow for AmbientTalk language values to be unquoted into parsetrees,
  97 * a native object is considered to be a valid ambienttalk expression. 
  98 *
  99 * @author tvcutsem, smostinc
 100 */
 101public abstract class NativeATObject implements ATObject, ATExpression, Serializable {
 102	
 103    protected NativeATObject() {};
 104
 105    /**
 106     * Asynchronous messages ( <tt>o<-m( args )</tt> ) sent in the context of an object o (i.e. 
 107     * sent in a method or closure where the self pseudovariable is bound to o)  are 
 108     * delegated to the base-level send method of the actor in which the object o is 
 109     * contained.
 110     */
 111    public ATObject meta_send(ATObject receiver, ATAsyncMessage message) throws InterpreterException {
 112    	return OBJLexicalRoot._INSTANCE_.base_reflectOnActor().base_send(receiver, message);
 113    }
 114
 115    /**
 116     * When a local object reference is used as an eventual reference by sending it an
 117     * asynchronous message, the object simply schedules the message in its owner's
 118     * message queue and returns <tt>nil</tt> immediately. The message is later transformed
 119     * into a method invocation (in a later actor execution "turn").
 120     * 
 121     * Note: in pre-2.9 versions of AmbientTalk, this method was invoked in the later
 122     * execution turn and immediately performed the message processing. Now, this method
 123     * is invoked by the sender of an async message and allows custom eventual references
 124     * to return a value other than <tt>nil</tt> for an async message send.
 125     */
 126    public ATObject meta_receive(ATAsyncMessage message) throws InterpreterException {
 127    	ELActor.currentActor().acceptSelfSend(this, message);
 128		return Evaluator.getNil();
 129    }
 130    
 131	/**
 132	 * An ambienttalk object can respond to a message if a corresponding field or method exists
 133	 * either in the receiver object locally, or in one of its dynamic parents.
 134	 * Fields also implicitly define a mutator whose name has the form <tt>field:=</tt>.
 135	 */
 136	public ATBoolean meta_respondsTo(ATSymbol selector) throws InterpreterException {
 137		if (this.hasLocalField(selector) || this.hasLocalMethod(selector)) {
 138			return NATBoolean._TRUE_;
 139		} else {
 140			if (selector.isAssignmentSymbol()) {
 141				if (this.hasLocalField(selector.asAssignmentSymbol().base_fieldName())) {
 142					return NATBoolean._TRUE_;
 143				}
 144			}
 145		}
 146		return base_super().meta_respondsTo(selector);
 147	}
 148
 149    /**
 150     * By default, when a selection is not understood by a primitive object, an error is raised.
 151     */
 152    public ATClosure meta_doesNotUnderstand(ATSymbol selector) throws InterpreterException {
 153        throw new XSelectorNotFound(selector, this);
 154    }
 155    
 156    /* ------------------------------------------
 157      * -- Slot accessing and mutating protocol --
 158      * ------------------------------------------ */
 159
 160	public ATNil meta_defineField(ATSymbol name, ATObject value) throws InterpreterException {
 161        throw new XIllegalOperation("Cannot add fields to " + Evaluator.valueNameOf(this.getClass()));
 162    }
 163
 164    /* ------------------------------------
 165      * -- Extension and cloning protocol --
 166      * ------------------------------------ */
 167
 168    public ATObject meta_clone() throws InterpreterException {
 169        throw new XIllegalOperation("Cannot clone a native object of type " + this.getClass().getName());
 170    }
 171
 172    public ATObject meta_newInstance(ATTable initargs) throws InterpreterException {
 173        return Reflection.upInstanceCreation(this, initargs);
 174    }
 175    
 176    /* ---------------------------------
 177      * -- Structural Access Protocol  --
 178      * --------------------------------- */
 179
 180    public ATNil meta_addField(ATField field) throws InterpreterException {
 181        throw new XIllegalOperation("Cannot add fields to " + Evaluator.valueNameOf(this.getClass()));
 182    }
 183
 184    public ATNil meta_addMethod(ATMethod method) throws InterpreterException {
 185        throw new XIllegalOperation("Cannot add methods to " + Evaluator.valueNameOf(this.getClass()));
 186    }
 187
 188    public ATField meta_grabField(ATSymbol fieldName) throws InterpreterException {
 189    	throw new XSelectorNotFound(fieldName, this);
 190    }
 191
 192    public ATMethod meta_grabMethod(ATSymbol methodName) throws InterpreterException {
 193        return Reflection.downBaseLevelMethod(this, methodName);
 194    }
 195
 196    public ATTable meta_listFields() throws InterpreterException {
 197    	return NATTable.EMPTY;
 198    }
 199
 200    public ATTable meta_listMethods() throws InterpreterException {
 201    	return NATTable.atValue(Reflection.downBaseLevelMethods(this));
 202    }
 203    
 204    public ATNil meta_addSlot(ATMethod method) throws InterpreterException {
 205    	return this.meta_addMethod(method);
 206    }
 207    
 208    public ATMethod meta_grabSlot(ATSymbol methodName) throws InterpreterException {
 209        try {
 210        	return this.meta_grabMethod(methodName);
 211        } catch(XSelectorNotFound e) {
 212        	e.catchOnlyIfSelectorEquals(methodName);
 213        	if (methodName.isAssignmentSymbol()) {
 214            	ATField mutator = this.meta_grabField(methodName.asAssignmentSymbol().base_fieldName());
 215            	return mutator.base_mutator();
 216        	} else {
 217            	ATField accessor = this.meta_grabField(methodName);
 218            	return accessor.base_accessor();
 219        	}
 220        }
 221    }
 222    
 223    public ATTable meta_listSlots() throws InterpreterException {
 224    	ATObject[] fields = this.meta_listFields().asNativeTable().elements_;
 225    	ATObject[] methods = this.meta_listMethods().asNativeTable().elements_;
 226    	
 227    	int fieldLength = fields.length * 2;
 228    	ATObject[] slots = new ATObject[fieldLength + methods.length];
 229    	int i = 0;
 230    	// add field accessors and mutators
 231    	for (; i < fieldLength ; i+=2) {
 232    		ATField field = (ATField) fields[i/2];
 233    		slots[i] = field.base_accessor();
 234        	slots[i+1] = field.base_mutator();
 235    	}
 236    	// add regular methods
 237    	for (; i < fieldLength + methods.length ; i++) {
 238    		slots[i] = methods[i - fieldLength];
 239    	}
 240    	
 241    	return NATTable.atValue(slots);
 242    }
 243
 244    /* ---------------------------------
 245      * -- Abstract Grammar Protocol   --
 246      * --------------------------------- */
 247
 248    /**
 249     * All NATObjects which are not Abstract Grammar elements are self-evaluating.
 250     */
 251    public ATObject meta_eval(ATContext ctx) throws InterpreterException {
 252        return this;
 253    }
 254
 255    /**
 256     * Quoting a native object returns itself, except for pure AG elements.
 257     */
 258    public ATObject meta_quote(ATContext ctx) throws InterpreterException {
 259        return this;
 260    }
 261
 262    public abstract NATText meta_print() throws InterpreterException;
 263
 264    /* ------------------------------
 265      * -- ATObject Mirror Fields   --
 266      * ------------------------------ */
 267
 268    /**
 269     * Native objects have a SHARES-A parent link to 'nil', by default.
 270     */
 271    public ATBoolean meta_isExtensionOfParent() throws InterpreterException {
 272        return NATBoolean.atValue((NATObject._SHARES_A_));
 273    };
 274
 275    /**
 276     * By default numbers, tables and so on have root as their lexical parent.
 277     */
 278    public ATObject impl_lexicalParent() throws InterpreterException {
 279        return Evaluator.getGlobalLexicalScope();
 280    }
 281    
 282	public ATBoolean meta_isCloneOf(ATObject original) throws InterpreterException {
 283		return NATBoolean.atValue(
 284				this.getClass() == original.getClass());
 285	}
 286
 287	public ATBoolean meta_isRelatedTo(ATObject object) throws InterpreterException {
 288		return this.meta_isCloneOf(object);
 289	}
 290	
 291    /* ---------------------------------
 292     * -- Type Testing and Querying --
 293     * --------------------------------- */
 294	
 295    /**
 296     * Native objects implement the type test non-recursively: only the type tags
 297     * returned by {@link this#meta_getTypeTags()} are tested against.
 298     */
 299    public ATBoolean meta_isTaggedAs(ATTypeTag type) throws InterpreterException {
 300    	ATObject[] types = this.meta_typeTags().asNativeTable().elements_;
 301    	for (int i = 0; i < types.length; i++) {
 302			if (types[i].asTypeTag().base_isSubtypeOf(type).asNativeBoolean().javaValue) {
 303				return NATBoolean._TRUE_;
 304			}
 305		}
 306    	return NATBoolean._FALSE_;
 307    }
 308    
 309    /**
 310     * By default, a native object (and also nil) has no type tags.
 311     */
 312    public ATTable meta_typeTags() throws InterpreterException {
 313    	return NATTable.EMPTY;
 314    }
 315	
 316    /* -----------------------------
 317     * -- Object Passing protocol --
 318     * ----------------------------- */
 319
 320    /**
 321     * This method allows objects to decide which object should be serialized in their
 322     * stead when they are passed as argument in an asynchronous message send that
 323     * crosses actor boundaries.
 324     */
 325    public abstract ATObject meta_pass() throws InterpreterException;
 326	
 327	/**
 328	 * Delegate the responsibility of serialization to the AT/2 meta-level 
 329	 */
 330	public Object writeReplace() throws ObjectStreamException {
 331		try {
 332			return this.meta_pass();
 333		} catch(InterpreterException e) {
 334			throw new InvalidObjectException("Failed to pass object " + this + ": " + e.getMessage());
 335		}
 336	}
 337	
 338    public abstract ATObject meta_resolve() throws InterpreterException;
 339	
 340	/**
 341	 * Delegate the responsibility of deserialization to the AT/2 meta-level 
 342	 */
 343	public Object readResolve() throws ObjectStreamException {
 344		try {
 345			return this.meta_resolve();
 346		} catch(InterpreterException e) {
 347			throw new SerializationException(e);
 348		}
 349	}
 350
 351    /* ---------------------------------
 352      * -- Value Conversion Protocol   --
 353      * --------------------------------- */
 354
 355    public boolean isSymbol() throws InterpreterException {
 356        return false;
 357    }
 358
 359    public boolean isTable() throws InterpreterException {
 360        return false;
 361    }
 362
 363    public boolean isCallFrame() throws InterpreterException {
 364        return false;
 365    }
 366
 367    public boolean isUnquoteSplice() throws InterpreterException {
 368        return false;
 369    }
 370
 371    public boolean isVariableAssignment() throws InterpreterException {
 372        return false;
 373    }
 374    
 375    public boolean isSplice() throws InterpreterException {
 376        return false;
 377    }
 378    
 379    public boolean isMessageCreation() throws InterpreterException {
 380    	return false;
 381    }
 382
 383    public boolean isAmbientTalkObject() { 
 384    	return false;
 385    }
 386    
 387    public boolean isMirage() {
 388    	return false;
 389    }
 390    
 391    public boolean isJavaObjectUnderSymbiosis() {
 392    	return false;
 393    }
 394
 395    public boolean isNativeBoolean() {
 396        return false;
 397    }
 398    
 399    public boolean isNativeText() {
 400        return false;
 401    }
 402    
 403	public boolean isNativeNumber() {
 404		return false;
 405	}
 406
 407    public boolean isNativeField() {
 408        return false;
 409    }
 410    
 411    public boolean isTypeTag() throws InterpreterException {
 412        return false;
 413    }
 414    
 415	public boolean isNativeFarReference() {
 416		return false;
 417	}
 418    
 419    // Conversions for concurrency and distribution related object
 420    public boolean isFarReference() throws InterpreterException {
 421    	return false;
 422    }
 423    
 424    public boolean isNativeFraction() { return false; }
 425    public boolean isNativeIntrospectiveMirror() { return false; }
 426	public boolean isJavaClassUnderSymbiosis() { return false; }
 427	public boolean isJavaMethodUnderSymbiosis() { return false; }
 428	public boolean isNativeDelegateMethod() { return false; }
 429	
 430    public ATClosure asClosure() throws InterpreterException {
 431        throw new XTypeMismatch(ATClosure.class, this);
 432    }
 433
 434    public ATSymbol asSymbol() throws InterpreterException {
 435        throw new XTypeMismatch(ATSymbol.class, this);
 436    }
 437
 438    public ATTable asTable() throws InterpreterException {
 439        throw new XTypeMismatch(ATTable.class, this);
 440    }
 441
 442    public ATBoolean asBoolean() throws InterpreterException {
 443        throw new XTypeMismatch(ATBoolean.class, this);
 444    }
 445
 446    public ATNumber asNumber() throws InterpreterException {
 447        throw new XTypeMismatch(ATNumber.class, this);
 448    }
 449
 450    public ATMessage asMessage() throws InterpreterException {
 451        throw new XTypeMismatch(ATMessage.class, this);
 452    }
 453    
 454    public ATMethodInvocation asMethodInvocation() throws InterpreterException {
 455        throw new XTypeMismatch(ATMethodInvocation.class, this);
 456    }
 457
 458    public ATField asField() throws InterpreterException {
 459        throw new XTypeMismatch(ATField.class, this);
 460    }
 461
 462    public ATMethod asMethod() throws InterpreterException {
 463        throw new XTypeMismatch(ATMethod.class, this);
 464    }
 465
 466    public ATHandler asHandler() throws InterpreterException {
 467    	throw new XTypeMismatch(ATHandler.class, this);
 468    }
 469
 470    public ATTypeTag asTypeTag() throws InterpreterException {
 471	    throw new XTypeMismatch(ATTypeTag.class, this);
 472    }
 473    
 474    public ATFarReference asFarReference() throws InterpreterException {
 475  	    throw new XTypeMismatch(ATFarReference.class, this);
 476  	}
 477    
 478    public ATAsyncMessage asAsyncMessage() throws InterpreterException {
 479  	    throw new XTypeMismatch(ATAsyncMessage.class, this);
 480  	}
 481    
 482    public ATActorMirror asActorMirror() throws InterpreterException {
 483    	throw new XTypeMismatch(ATActorMirror.class, this);
 484    }
 485    
 486    // Conversions for abstract grammar elements
 487
 488    public ATStatement asStatement() throws InterpreterException {
 489        throw new XTypeMismatch(ATStatement.class, this);
 490    }
 491
 492    public ATDefinition asDefinition() throws InterpreterException {
 493        throw new XTypeMismatch(ATDefinition.class, this);
 494    }
 495
 496    public ATExpression asExpression() throws InterpreterException {
 497        return this;
 498    }
 499
 500    public ATBegin asBegin() throws InterpreterException {
 501        throw new XTypeMismatch(ATBegin.class, this);
 502    }
 503
 504    public ATMessageCreation asMessageCreation() throws InterpreterException {
 505        throw new XTypeMismatch(ATMessageCreation.class, this);
 506    }
 507
 508    public ATQuote asQuote() throws InterpreterException {
 509        throw new XTypeMismatch(ATQuote.class, this);
 510    }
 511
 512    public ATUnquoteSplice asUnquoteSplice() throws InterpreterException {
 513        throw new XTypeMismatch(ATUnquoteSplice.class, this);
 514    }
 515
 516    public ATAssignVariable asVariableAssignment() throws InterpreterException {
 517        throw new XTypeMismatch(ATAssignVariable.class, this);
 518    }
 519    
 520    public ATSplice asSplice() throws InterpreterException {
 521        throw new XTypeMismatch(ATSplice.class, this);
 522    }
 523    
 524    public ATLetter asLetter() throws InterpreterException {
 525    	throw new XTypeMismatch(ATLetter.class, this);
 526    }
 527    
 528    // Conversions for native values
 529    public NATObject asAmbientTalkObject() throws XTypeMismatch {
 530    	throw new XTypeMismatch(NATObject.class, this);
 531    }
 532
 533    public NATMirage asMirage() throws XTypeMismatch {
 534    	throw new XTypeMismatch(NATMirage.class, this);
 535    }
 536
 537    public NATNumber asNativeNumber() throws XTypeMismatch {
 538        throw new XTypeMismatch(NATNumber.class, this);
 539    }
 540
 541    public NATFraction asNativeFraction() throws XTypeMismatch {
 542        throw new XTypeMismatch(NATFraction.class, this);
 543    }
 544
 545    public NATText asNativeText() throws XTypeMismatch {
 546    	throw new XTypeMismatch(NATText.class, this);
 547    }
 548
 549    public NATTable asNativeTable() throws XTypeMismatch {
 550        throw new XTypeMismatch(NATTable.class, this);
 551    }
 552
 553    public NATBoolean asNativeBoolean() throws XTypeMismatch {
 554        throw new XTypeMismatch(NATBoolean.class, this);
 555    }
 556    
 557    public NATNumeric asNativeNumeric() throws XTypeMismatch {
 558        throw new XTypeMismatch(NATNumeric.class, this);
 559    }
 560    
 561    public NATFarReference asNativeFarReference() throws XTypeMismatch {
 562    	throw new XTypeMismatch(NATFarReference.class, this);
 563    }
 564
 565    public JavaObject asJavaObjectUnderSymbiosis() throws XTypeMismatch {
 566    	throw new XTypeMismatch(JavaObject.class, this);
 567    }
 568    
 569    public JavaClass asJavaClassUnderSymbiosis() throws XTypeMismatch {
 570	    throw new XTypeMismatch(JavaClass.class, this);
 571    }
 572    
 573    public JavaMethod asJavaMethodUnderSymbiosis() throws XTypeMismatch {
 574	    throw new XTypeMismatch(JavaMethod.class, this);
 575    }
 576    
 577    public DelegateMethod asNativeDelegateMethod() throws XTypeMismatch {
 578	    throw new XTypeMismatch(DelegateMethod.class, this);
 579    }
 580    
 581    public NATIntrospectiveMirror asNativeIntrospectiveMirror() throws XTypeMismatch {
 582	    throw new XTypeMismatch(NATIntrospectiveMirror.class, this);
 583    }
 584    
 585    /**
 586     * Only true objects have a dynamic pointer, native objects denote 'nil' to
 587     * be their dynamic parent when asked for it. Note that, for native objects,
 588     * 'super' is a read-only field (i.e. only an accessor for the virtual field exists).
 589     */
 590    public ATObject base_super() throws InterpreterException {
 591        return Evaluator.getNil();
 592    };
 593
 594    public String toString() {
 595        return Evaluator.toString(this);
 596    }
 597    
 598    /**
 599     * Java method invocations of equals are transformed into
 600     * AmbientTalk '==' method invocations.
 601     */
 602    public boolean equals(Object other) {
 603    	try {
 604    		if (other instanceof ATObject) {
 605    			return this.base__opeql__opeql_((ATObject) other).asNativeBoolean().javaValue;
 606    		}
 607    	} catch (InterpreterException e) {
 608    		Logging.Actor_LOG.warn("Error during equality testing:", e);
 609    	}
 610    	return false; 
 611    }
 612    
 613    public ATBoolean impl_identityEquals(ATObject other) throws InterpreterException {
 614    	return NATBoolean.atValue(other == this);
 615    }
 616    
 617	/**
 618	 * By default, two AmbientTalk objects are equal if they are the
 619	 * same object, or one is a proxy for the same object.
 620	 */
 621    public ATBoolean base__opeql__opeql_(ATObject other) throws InterpreterException {
 622		// by default, ATObjects use pointer equality
 623		return NATBoolean.atValue(this == other);
 624    }
 625    
 626    /*public ATObject base_new(ATObject[] initargs) throws InterpreterException {
 627    	return this.meta_newInstance(NATTable.atValue(initargs));
 628    }*/
 629    
 630    /*public ATObject base_init(ATObject[] initargs) throws InterpreterException {
 631    	return Evaluator.getNil();
 632    }*/
 633    
 634	/**
 635	 * This method is used to evaluate code of the form <tt>selector(args)</tt>
 636	 * or <tt>selector := arg</tt> within the scope of this object.
 637	 * 
 638	 * It dispatches to other implementation-level methods based on the selector.
 639	 */
 640	public ATObject impl_call(ATSymbol selector, ATTable arguments) throws InterpreterException {
 641		if (selector.isAssignmentSymbol()) {
 642			return this.impl_callMutator(selector.asAssignmentSymbol(), arguments);
 643		} else {
 644			return this.impl_callAccessor(selector, arguments);
 645		}
 646	}
 647
 648    /**
 649	 * Implements the interpretation of <tt>f(arg)</tt> inside the scope of a
 650	 * particular object.
 651	 * 
 652	 * - if f is bound to a local method, the method is applied
 653	 * - if f is bound to a field:
 654	 *   - if the field contains a closure, the closure is applied
 655	 *   - otherwise, the field is treated as a nullary closure and 'applied'
 656	 * - otherwise, the search for the selector continues in the lexical parent
 657	 */
 658	public ATObject impl_callAccessor(ATSymbol selector, ATTable arguments) throws InterpreterException {
 659		if(this.hasLocalMethod(selector)) {
 660			// apply the method with a context ctx where 
 661			//  ctx.scope = the implementing scope, being this object
 662			//  ctx.self  = the receiver, being in this case again the implementor
 663			return this.getLocalMethod(selector).base_apply(arguments, new NATContext(this, this));
 664		} else {
 665			if (this.hasLocalField(selector)) {
 666				ATObject fieldValue = this.getLocalField(selector);
 667				
 668				if (fieldValue.meta_isTaggedAs(NativeTypeTags._CLOSURE_).asNativeBoolean().javaValue) {
 669					return fieldValue.asClosure().base_apply(arguments);
 670				} else {
 671					NativeClosure.checkNullaryArguments(selector, arguments);
 672					return fieldValue;
 673				}
 674			} else {
 675				return this.impl_lexicalParent().impl_callAccessor(selector, arguments);
 676			}
 677		}
 678	}
 679
 680    /**
 681	 * Implements the interpretation of <tt>x := arg</tt> inside the scope of a
 682	 * particular object.
 683	 * 
 684	 * - if x:= is bound to a local method, the method is applied
 685	 * - if x is bound to a field, the field is assigned if exactly one argument is given
 686	 * - otherwise, the search for the selector continues in the lexical parent
 687	 */
 688	public ATObject impl_callMutator(ATAssignmentSymbol selector, ATTable arguments) throws InterpreterException {
 689		if(this.hasLocalMethod(selector)) {
 690			// apply the method with a context ctx where 
 691			//  ctx.scope = the implementing scope, being this object
 692			//  ctx.self  = the receiver, being in this case again the implementor
 693			return this.getLocalMethod(selector).base_apply(arguments, new NATContext(this, this));
 694		} else {
 695			ATSymbol fieldSelector = selector.base_fieldName();
 696			if (this.hasLocalField(fieldSelector)) {
 697				ATObject value = NativeClosure.checkUnaryArguments(selector, arguments);
 698				this.setLocalField(fieldSelector, value);
 699				return value;
 700			} else {
 701				return this.impl_lexicalParent().impl_callMutator(selector, arguments);
 702			}
 703		}
 704	}	
 705	
 706    /**
 707	 * Implements the interpretation of <tt>x</tt> inside the scope of a
 708	 * particular object.
 709	 * 
 710	 * - if x is bound to a local method, the method is applied to <tt>[]</tt>
 711	 * - if x is bound to a field, the field's value is returned (even if it
 712	 *   contains a closure)
 713	 * - otherwise, the search for the selector continues in the lexical parent
 714	 */
 715	public ATObject impl_callField(ATSymbol selector) throws InterpreterException {
 716		// if selector is bound to a method, treat 'm' as 'm()'
 717		if(this.hasLocalMethod(selector)) {
 718			// apply the method with a context ctx where 
 719			//  ctx.scope = the implementing scope, being this object
 720			//  ctx.self  = the receiver, being in this case again the implementor
 721			return this.getLocalMethod(selector).base_apply(NATTable.EMPTY, new NATContext(this, this));
 722		} else {
 723			if (this.hasLocalField(selector)) {
 724				// simply return the field's value, regardless of whether it is bound to a
 725				// closure or not
 726				return this.getLocalField(selector);
 727			} else {
 728				return this.impl_lexicalParent().impl_callField(selector);
 729			}
 730		}
 731	}
 732
 733	/**
 734	 * This method simply deconstructs the method invocation object and passes it on to
 735	 * the native implementation.
 736	 */
 737    public ATObject meta_invoke(ATObject delegate, ATMethodInvocation invocation) throws InterpreterException {
 738        return this.impl_invoke(delegate, invocation.base_selector(), invocation.base_arguments());
 739    }
 740    
 741	/**
 742	 * This method dispatches to specific invocation primitives
 743	 * depending on whether or not the given selector denotes an assignment.
 744	 */
 745    public ATObject impl_invoke(ATObject delegate, ATSymbol selector, ATTable arguments) throws InterpreterException {
 746        // If the selector is an assignment symbol (i.e. `field:=) try to assign the corresponding field
 747		if (selector.isAssignmentSymbol()) {
 748			return this.impl_invokeMutator(delegate, selector.asAssignmentSymbol(), arguments);
 749		} else {
 750			return this.impl_invokeAccessor(delegate, selector, arguments);
 751		}
 752    }
 753    
 754    /**
 755	 * Implements the interpretation of <tt>o.m(arg)</tt>.
 756	 * 
 757	 * - if m is bound to a local method of o, the method is applied
 758	 * - if m is bound to a field of o:
 759	 *   - if the field contains a closure, the closure is applied
 760	 *   - otherwise, the field is treated as a nullary closure and 'applied'
 761	 * - otherwise, the search for the selector continues in the dynamic parent
 762	 */
 763	public ATObject impl_invokeAccessor(ATObject receiver, ATSymbol selector, ATTable arguments) throws InterpreterException {
 764		if (this.hasLocalMethod(selector)) {
 765			// immediately execute the method in the context ctx where
 766			//  ctx.scope = the implementing scope, being this object, under which an additional callframe will be inserted
 767			//  ctx.self  = the late bound receiver, being the passed receiver
 768			return this.getLocalMethod(selector).base_apply(arguments, new NATContext(this, receiver));
 769		} else {
 770			if (this.hasLocalField(selector)) {
 771				ATObject fieldValue = this.getLocalField(selector);
 772				
 773				if (fieldValue.meta_isTaggedAs(NativeTypeTags._CLOSURE_).asNativeBoolean().javaValue) {
 774					return fieldValue.asClosure().base_apply(arguments);
 775				} else {
 776					NativeClosure.checkNullaryArguments(selector, arguments);
 777					return fieldValue;
 778				}
 779			} else {
 780				return base_super().impl_invokeAccessor(receiver, selector, arguments);
 781			}
 782		}
 783	}
 784	
 785    /**
 786	 * Implements the interpretation of <tt>o.x := arg</tt>.
 787	 * 
 788	 * - if x:= is bound to a local method of o, the method is applied to the arguments.
 789	 * - if x is bound to a field of o, the field is treated as a unary mutator method
 790	 *   that assigns the field and 'applied' to the given arguments.
 791	 * - otherwise, the search for the selector continues in the dynamic parent
 792	 */
 793	public ATObject impl_invokeMutator(ATObject receiver, ATAssignmentSymbol selector, ATTable arguments) throws InterpreterException {
 794		if (this.hasLocalMethod(selector)) {
 795			// immediately execute the method in the context ctx where
 796			//  ctx.scope = the implementing scope, being this object, under which an additional callframe will be inserted
 797			//  ctx.self  = the late bound receiver, being the passed receiver
 798			return this.getLocalMethod(selector).base_apply(arguments, new NATContext(this, receiver));
 799		} else {
 800			// try to treat a local field as a mutator
 801			ATSymbol fieldSelector = selector.base_fieldName();
 802			if (this.hasLocalField(fieldSelector)) {
 803				ATObject value = NativeClosure.checkUnaryArguments(selector, arguments);
 804				this.setLocalField(fieldSelector, value);
 805				return value;
 806			} else {
 807				// if no field matching the selector exists, delegate to the parent
 808				return base_super().impl_invokeMutator(receiver, selector, arguments);
 809			}
 810		}
 811	}
 812
 813    /**
 814	 * Implements the interpretation of <tt>o.x</tt>.
 815	 * 
 816	 * - if x is bound to a local method of o, the method is applied to <tt>[]</tt>
 817	 * - if x is bound to a field of o, the field's value is returned (even if it
 818	 *   contains a closure).
 819	 * - otherwise, the search for the selector continues in the dynamic parent
 820	 */
 821	public ATObject meta_invokeField(ATObject receiver, ATSymbol selector) throws InterpreterException {
 822		// if selector is bound to a method, treat 'o.m' as 'o.m()'
 823		if (this.hasLocalMethod(selector)) {
 824			// immediately execute the method in the context ctx where
 825			//  ctx.scope = the implementing scope, being this object, under which an additional callframe will be inserted
 826			//  ctx.self  = the late bound receiver, being the passed receiver
 827			return this.getLocalMethod(selector).base_apply(NATTable.EMPTY, new NATContext(this, receiver));
 828		} else {
 829			if (this.hasLocalField(selector)) {
 830				// return the field's value, regardless of whether it is a closure or not
 831				return this.getLocalField(selector);
 832			} else {
 833				return base_super().meta_invokeField(receiver, selector);
 834			}
 835		}
 836	}
 837	
 838    /**
 839	 * This operation dispatches to more specific implementation-level methods depending
 840	 * on the type of the selector.
 841	 */
 842	public ATClosure impl_lookup(ATSymbol selector) throws InterpreterException {
 843		if (selector.isAssignmentSymbol()) {
 844			return this.impl_lookupMutator(selector.asAssignmentSymbol());
 845		} else {
 846			return this.impl_lookupAccessor(selector);
 847		}
 848	}
 849	
 850    /**
 851	 * Implements the interpretation of <tt>&f</tt> in the scope of this object.
 852	 * 
 853	 * - if f is bound to a local method, a closure wrapping the method is returned
 854	 * - if f is bound to a field of o, an accessor closure is returned which yields
 855	 * the field's value upon application.
 856	 * - otherwise, the search for the selector continues in the lexical parent
 857	 */
 858	public ATClosure impl_lookupAccessor(final ATSymbol selector) throws InterpreterException {
 859		if (this.hasLocalMethod(selector)) {
 860			// return a new closure (mth, ctx) where
 861			//  mth = the method found in this object
 862			//  ctx.scope = the implementing scope, being this object
 863			//  ctx.self  = the late bound receiver, being the passed receiver
 864			//  ctx.super = the parent of the implementor
 865			return this.getLocalMethod(selector).base_wrap(this, this);
 866		} else {
 867			// try to wrap a local field in an accessor
 868			if(this.hasLocalField(selector)) {
 869				final NativeATObject scope = this;
 870				return new NativeClosure.Accessor(selector, this) {
 871					protected ATObject access() throws InterpreterException {
 872						return scope.getLocalField(selector);
 873					}
 874				};
 875			} else {
 876				return this.impl_lexicalParent().impl_lookupAccessor(selector);
 877			}
 878		}
 879	}
 880
 881    /**
 882	 * Implements the interpretation of <tt>&f:=</tt> in the scope of this object.
 883	 * 
 884	 * - if f:= is bound to a local method, a closure wrapping the method is returned
 885	 * - if f is bound to a field of o, a mutator closure is returned which assigns
 886	 * the field upon application.
 887	 * - otherwise, the search for the selector continues in the lexical parent
 888	 */
 889	public ATClosure impl_lookupMutator(ATAssignmentSymbol selector) throws InterpreterException {
 890		if (this.hasLocalMethod(selector)) {
 891			// return a new closure (mth, ctx) where
 892			//  mth = the method found in this object
 893			//  ctx.scope = the implementing scope, being this object
 894			//  ctx.self  = the late bound receiver, being the passed receiver
 895			//  ctx.super = the parent of the implementor
 896			return this.getLocalMethod(selector).base_wrap(this, this);
 897		} else {
 898			final ATSymbol fieldSelector = selector.base_fieldName();
 899			// try to wrap a local field in a mutator
 900			if(this.hasLocalField(fieldSelector)) {
 901				final NativeATObject scope = this;
 902				return new NativeClosure.Mutator(selector, this) {
 903					protected ATObject mutate(ATObject arg) throws InterpreterException {
 904						scope.setLocalField(fieldSelector, arg);
 905						return arg;
 906					}
 907				};
 908			} else {
 909				return this.impl_lexicalParent().impl_lookupMutator(selector);
 910			}
 911		}
 912	}
 913
 914	/**
 915	 * select should dispatch to specific selection primitives
 916	 * depending on whether or not the given selector denotes an assignment.
 917	 */
 918    public ATClosure meta_select(ATObject receiver, final ATSymbol selector) throws InterpreterException {
 919		if (selector.isAssignmentSymbol()) {
 920			return this.impl_selectMutator(receiver, selector.asAssignmentSymbol());
 921		} else {
 922			return this.impl_selectAccessor(receiver, selector);
 923		}
 924    }
 925    
 926    /**
 927	 * Implements the interpretation of <tt>o.&m</tt>.
 928	 * 
 929	 * - if m is bound to a local method, a closure wrapping the method is returned
 930	 * - if m is bound to a field of o, an accessor closure is returned which yields
 931	 * the field's value upon application.
 932	 * - otherwise, the search for the selector continues in the dynamic parent
 933	 */
 934    public ATClosure impl_selectAccessor(ATObject receiver, final ATSymbol selector) throws InterpreterException {
 935    	if (this.hasLocalMethod(selector)) {
 936    		// return a new closure (mth, ctx) where
 937    		//  mth = the method found in this object
 938    		//  ctx.scope = the implementing scope, being this object
 939    		//  ctx.self  = the late bound receiver, being the passed receiver
 940    		//  ctx.super = the parent of the implementor
 941    		return this.getLocalMethod(selector).base_wrap(this, receiver);
 942    	} else {
 943    		if (this.hasLocalField(selector)) {
 944    			final NativeATObject scope = this;
 945    			return new NativeClosure.Accessor(selector, this) {
 946    				protected ATObject access() throws InterpreterException {
 947    					return scope.getLocalField(selector);
 948    				}
 949    			};
 950    		} else {
 951    			return base_super().impl_selectAccessor(receiver, selector);
 952    		}
 953    	}
 954    }
 955
 956    /**
 957	 * Implements the interpretation of <tt>o.&m:=</tt>.
 958	 * 
 959	 * - if m:= is bound to a local method, a closure wrapping the method is returned
 960	 * - if m is bound to a field of o, a mutator closure is returned which assigns
 961	 * the field upon application.
 962	 * - otherwise, the search for the selector continues in the dynamic parent
 963	 */
 964    public ATClosure impl_selectMutator(ATObject receiver, final ATAssignmentSymbol selector) throws InterpreterException {
 965    	if (this.hasLocalMethod(selector)) {
 966    		// return a new closure (mth, ctx) where
 967    		//  mth = the method found in this object
 968    		//  ctx.scope = the implementing scope, being this object
 969    		//  ctx.self  = the late bound receiver, being the passed receiver
 970    		//  ctx.super = the parent of the implementor
 971    		return this.getLocalMethod(selector).base_wrap(this, receiver);
 972    	} else {
 973    		// try to wrap a local field in a mutator
 974    		final ATSymbol fieldSelector = selector.base_fieldName();
 975    		if (this.hasLocalField(fieldSelector)) {
 976    			final NativeATObject scope = this;
 977    			return new NativeClosure.Mutator(selector, this) {
 978    				protected ATObject mutate(ATObject arg) throws InterpreterException {
 979    					scope.setLocalField(fieldSelector, arg);
 980    					return arg;
 981    				}
 982    			};
 983    		} else {
 984    			// if no field matching the selector exists, delegate to the parent
 985    			return base_super().impl_selectMutator(receiver, selector);
 986    		}
 987    	}
 988    }
 989	
 990	/** native objects have no fields */
 991	protected boolean hasLocalField(ATSymbol sym) throws InterpreterException {
 992		return false;
 993	}
 994
 995	/**
 996	 * A native Java object has a local method if it implements a
 997	 * native Java method corresponding to the selector prefixed by 'base_'.
 998	 */
 999	protected boolean hasLocalMethod(ATSymbol atSelector) throws InterpreterException {
1000        String jSelector = Reflection.upBaseLevelSelector(atSelector);
1001        return Reflection.upRespondsTo(this, jSelector);
1002	}
1003	
1004	protected ATObject getLocalField(ATSymbol selector) throws InterpreterException {
1005		throw new XSelectorNotFound(selector, this);
1006	}
1007	
1008	protected ATMethod getLocalMethod(ATSymbol selector) throws InterpreterException {
1009		String methSelector = Reflection.upBaseLevelSelector(selector);
1010		return Reflection.upMethodSelection(this, methSelector, selector);
1011	}
1012	
1013	protected void setLocalField(ATSymbol selector, ATObject value) throws InterpreterException {
1014		throw new XSelectorNotFound(selector, this);
1015	}
1016	
1017}