PageRenderTime 59ms CodeModel.GetById 14ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

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

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