PageRenderTime 87ms CodeModel.GetById 26ms app.highlight 54ms RepoModel.GetById 1ms app.codeStats 0ms

/interpreter/tags/at2-build270707/src/edu/vub/at/objects/natives/NativeATObject.java

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