PageRenderTime 50ms CodeModel.GetById 13ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

/interpreter/tags/at2-build190607/src/edu/vub/at/objects/natives/NATNil.java

http://ambienttalk.googlecode.com/
Java | 639 lines | 351 code | 102 blank | 186 comment | 7 complexity | aad26cfd87ebc36bba3a34b6bdf70f86 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.exceptions.XUnassignableField;
 41import edu.vub.at.exceptions.XUndefinedSlot;
 42import edu.vub.at.objects.ATBoolean;
 43import edu.vub.at.objects.ATClosure;
 44import edu.vub.at.objects.ATContext;
 45import edu.vub.at.objects.ATField;
 46import edu.vub.at.objects.ATHandler;
 47import edu.vub.at.objects.ATMessage;
 48import edu.vub.at.objects.ATMethod;
 49import edu.vub.at.objects.ATNil;
 50import edu.vub.at.objects.ATNumber;
 51import edu.vub.at.objects.ATObject;
 52import edu.vub.at.objects.ATTypeTag;
 53import edu.vub.at.objects.ATTable;
 54import edu.vub.at.objects.grammar.ATAssignVariable;
 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.Reflection;
 65import edu.vub.at.objects.symbiosis.JavaClass;
 66import edu.vub.at.objects.symbiosis.JavaObject;
 67import edu.vub.at.objects.symbiosis.SymbioticATObjectMarker;
 68import edu.vub.at.util.logging.Logging;
 69
 70import java.io.InvalidObjectException;
 71import java.io.ObjectStreamException;
 72import java.io.Serializable;
 73
 74/**
 75 * NATNil implements default semantics for all test and conversion methods.
 76 * It also implements the default metaobject protocol semantics for native
 77 * AmbientTalk objects.
 78 * <p>
 79 * To allow for AmbientTalk language values to be unquoted into parsetrees,
 80 * nil is considered to be a valid ambienttalk expression. 
 81 *
 82 * @author smostinc
 83 * @author tvcutsem
 84 */
 85public class NATNil implements ATExpression, ATNil, Serializable {
 86	
 87    protected NATNil() {};
 88
 89    /**
 90     * This field holds the sole instance of this class. In AmbientTalk,
 91     * this is the object that represents <tt>nil</tt>.
 92     */
 93    public final static NATNil _INSTANCE_ = new NATNil();
 94
 95    /* ------------------------------
 96      * -- Message Sending Protocol --
 97      * ------------------------------ */
 98
 99	/**
100     * Asynchronous messages ( o<-m( args )) sent in the context of an object o (i.e. 
101     * sent in a method or closure where the self pseudovariable is bound to o)  are 
102     * delegated to the base-level send method of the actor in which the object o is 
103     * contained.
104     */
105    public ATObject meta_send(ATAsyncMessage message) throws InterpreterException {
106    	return OBJLexicalRoot._INSTANCE_.base_getActor().base_send(message);
107    }
108
109    /**
110     * By default, when an object receives an incoming asynchronous message, it tells
111     * the message to process itself. The message's default behaviour is to subsequently
112     * invoke the method corresponding to the message's selector on this object.
113     */
114    public ATObject meta_receive(ATAsyncMessage message) throws InterpreterException {
115    	return message.base_process(this);
116    }
117    
118    /**
119     * The default behaviour of 'invoke' for primitive non-object ambienttalk language values is
120     * to check whether the requested functionality is provided by a native Java method
121     * with the same selector, but prefixed with <tt>base_</tt>.
122     *
123     * Because an explicit AmbientTalk method invocation must be converted into an implicit
124     * Java method invocation, the invocation must be deified ('upped'). The result of the
125     * upped invocation is a Java object, which must subsequently be 'downed' again.
126     * 
127     * If no method to invoke is found, doesNotUnderstand is invoked which should
128     * return a closure to be invoked with the appropriate arguments.
129     */
130    public ATObject meta_invoke(ATObject receiver, ATSymbol atSelector, ATTable arguments) throws InterpreterException {
131        try {
132			String jSelector = Reflection.upBaseLevelSelector(atSelector);
133			return Reflection.upInvocation(this /*receiver*/, jSelector, atSelector, arguments);
134		} catch (XSelectorNotFound e) {
135			e.catchOnlyIfSelectorEquals(atSelector);
136			return receiver.meta_doesNotUnderstand(atSelector).asClosure().base_apply(arguments);
137		}
138    }
139
140    /**
141     * An ambienttalk language value can respond to a message if it implements
142     * a native Java method corresponding to the selector prefixed by 'base_'.
143     */
144    public ATBoolean meta_respondsTo(ATSymbol atSelector) throws InterpreterException {
145        String jSelector = Reflection.upBaseLevelSelector(atSelector);
146        return NATBoolean.atValue(Reflection.upRespondsTo(this, jSelector));
147    }
148
149    /**
150     * By default, when a selection is not understood by a primitive object, an error is raised.
151     */
152    public ATObject meta_doesNotUnderstand(ATSymbol selector) throws InterpreterException {
153        throw new XSelectorNotFound(selector, this);
154    }
155    
156    /* ------------------------------------------
157      * -- Slot accessing and mutating protocol --
158      * ------------------------------------------ */
159
160    /**
161     * It is possible to select a method from any ambienttalk value provided that it
162     * offers the method in its provided interface. The result is a NativeMethod wrapper
163     * which encapsulates the reflective Method object as well as the receiver.
164     * 
165     * There exists a certain ambiguity in field selection on AmbientTalk implementation-level objects.
166     * When nativeObject.m is evaluated, the corresponding Java class must have a method named either
167     *  base_getM which means m is represented as a readable field, or
168     *  base_m which means m is represented as a method
169     */
170    public ATObject meta_select(ATObject receiver, ATSymbol selector) throws InterpreterException {
171        String jSelector = Reflection.upBaseFieldAccessSelector(selector);
172        try {
173            return Reflection.upFieldSelection(this, jSelector, selector);
174        } catch (XSelectorNotFound e) {
175        	e.catchOnlyIfSelectorEquals(selector);
176            jSelector = Reflection.upBaseLevelSelector(selector);
177
178            try {
179				return Reflection.upMethodSelection(this, jSelector, selector);
180			} catch (XSelectorNotFound e2) {
181				e2.catchOnlyIfSelectorEquals(selector);
182				return receiver.meta_doesNotUnderstand(selector);
183			}
184        }
185    }
186
187    /**
188     * A lookup can only be issued at the base level by writing <tt>selector</tt> inside the scope
189     * of a particular object. For primitive language values, this should not happen
190     * as no AmbientTalk code can be possibly nested within native code. However, using
191     * meta-programming a primitive object could be installed as the lexical parent of an AmbientTalk object.
192     *
193     * One particular case where this method will often be called is when a lookup reaches
194     * the lexical root, OBJLexicalRoot, which inherits this implementation.
195     *
196     * In such cases a lookup is treated exactly like a selection, where the 'original receiver'
197     * of the selection equals the primitive object.
198     */
199    public ATObject meta_lookup(ATSymbol selector) throws InterpreterException {
200        try {
201        	  return this.meta_select(this, selector);
202        } catch(XSelectorNotFound e) {
203        	  // transform selector not found in undefined variable access
204        	  throw new XUndefinedSlot("variable access", selector.base_getText().asNativeText().javaValue);
205        }
206    }
207
208    public ATNil meta_defineField(ATSymbol name, ATObject value) throws InterpreterException {
209        throw new XIllegalOperation("Cannot add fields to " + Evaluator.valueNameOf(this.getClass()));
210    }
211
212    /**
213     * Normally, a variable assignment cannot be performed on a native AmbientTalk object.
214     * This is because a variable assignment can normally be only raised by performing
215     * an assignment in the lexical scope of an object. However, using metaprogramming
216     * a native object could be installed as the lexical parent of an AT object. In such
217     * cases, variable assignment is treated as field assignment.
218     * 
219     * One particular case where this method will often be called is when a variable assignment reaches
220     * the lexical root, OBJLexicalRoot, which inherits this implementation.
221     */
222    public ATNil meta_assignVariable(ATSymbol name, ATObject value) throws InterpreterException {
223        return this.meta_assignField(this, name, value);
224    }
225
226    public ATNil meta_assignField(ATObject receiver, ATSymbol name, ATObject value) throws InterpreterException {
227    	String jSelector = Reflection.upBaseFieldMutationSelector(name);
228    	
229        // try to invoke a native base_setName method
230        try {	   
231           Reflection.upFieldAssignment(receiver, jSelector, name, value);
232		} catch (XSelectorNotFound e) {
233			e.catchOnlyIfSelectorEquals(name);
234			// if such a method does not exist, the field assignment has failed
235			throw new XUnassignableField(name.base_getText().asNativeText().javaValue);
236		}
237		
238        return NATNil._INSTANCE_;
239    }
240
241    /* ------------------------------------
242      * -- Extension and cloning protocol --
243      * ------------------------------------ */
244
245    public ATObject meta_clone() throws InterpreterException {
246        throw new XIllegalOperation("Cannot clone a native object of type " + this.getClass().getName());
247    }
248
249    public ATObject meta_newInstance(ATTable initargs) throws InterpreterException {
250        return Reflection.upInstanceCreation(this, initargs);
251    }
252    
253    /* ---------------------------------
254      * -- Structural Access Protocol  --
255      * --------------------------------- */
256
257    public ATNil meta_addField(ATField field) throws InterpreterException {
258        throw new XIllegalOperation("Cannot add fields to " + Evaluator.valueNameOf(this.getClass()));
259    }
260
261    public ATNil meta_addMethod(ATMethod method) throws InterpreterException {
262        throw new XIllegalOperation("Cannot add methods to " + Evaluator.valueNameOf(this.getClass()));
263    }
264
265    public ATField meta_grabField(ATSymbol fieldName) throws InterpreterException {
266        return Reflection.downBaseLevelField(this, fieldName);
267    }
268
269    public ATMethod meta_grabMethod(ATSymbol methodName) throws InterpreterException {
270        return Reflection.downBaseLevelMethod(this, methodName);
271    }
272
273    public ATTable meta_listFields() throws InterpreterException {
274        return NATTable.atValue(Reflection.downBaseLevelFields(this));
275    }
276
277    public ATTable meta_listMethods() throws InterpreterException {
278    	return NATTable.atValue(Reflection.downBaseLevelMethods(this));
279    }
280
281    /* ---------------------------------
282      * -- Abstract Grammar Protocol   --
283      * --------------------------------- */
284
285    /**
286     * All NATObjects which are not Abstract Grammar elements are self-evaluating.
287     */
288    public ATObject meta_eval(ATContext ctx) throws InterpreterException {
289        return this;
290    }
291
292    /**
293     * Quoting a native object returns itself, except for pure AG elements.
294     */
295    public ATObject meta_quote(ATContext ctx) throws InterpreterException {
296        return this;
297    }
298
299    public NATText meta_print() throws InterpreterException {
300        return NATText.atValue("nil");
301    }
302
303    /* ------------------------------
304      * -- ATObject Mirror Fields   --
305      * ------------------------------ */
306
307    /**
308     * Native objects have a SHARES-A parent link to 'nil', by default.
309     */
310    public ATBoolean meta_isExtensionOfParent() throws InterpreterException {
311        return NATBoolean.atValue((NATObject._SHARES_A_));
312    };
313
314    /**
315     * By default numbers, tables and so on do not have lexical parents,
316     */
317    public ATObject meta_getLexicalParent() throws InterpreterException {
318        return NATNil._INSTANCE_;
319    }
320
321    /* ---------------------------------
322      * -- Value Conversion Protocol   --
323      * --------------------------------- */
324
325    public boolean isSymbol() throws InterpreterException {
326        return false;
327    }
328
329    public boolean isTable() throws InterpreterException {
330        return false;
331    }
332
333    public boolean isCallFrame() throws InterpreterException {
334        return false;
335    }
336
337    public boolean isUnquoteSplice() throws InterpreterException {
338        return false;
339    }
340
341    public boolean isVariableAssignment() throws InterpreterException {
342        return false;
343    }
344    
345    public boolean isSplice() throws InterpreterException {
346        return false;
347    }
348    
349    public boolean isMessageCreation() throws InterpreterException {
350    	return false;
351    }
352
353    public boolean isAmbientTalkObject() { 
354    	return false;
355    }
356    
357    public boolean isJavaObjectUnderSymbiosis() {
358    	return false;
359    }
360
361    public boolean isNativeBoolean() {
362        return false;
363    }
364    
365    public boolean isNativeText() {
366        return false;
367    }
368
369    public boolean isNativeField() {
370        return false;
371    }
372    
373    public boolean isTypeTag() throws InterpreterException {
374        return false;
375    }
376    
377    public ATClosure asClosure() throws InterpreterException {
378        throw new XTypeMismatch(ATClosure.class, this);
379    }
380
381    public ATSymbol asSymbol() throws InterpreterException {
382        throw new XTypeMismatch(ATSymbol.class, this);
383    }
384
385    public ATTable asTable() throws InterpreterException {
386        throw new XTypeMismatch(ATTable.class, this);
387    }
388
389    public ATBoolean asBoolean() throws InterpreterException {
390        throw new XTypeMismatch(ATBoolean.class, this);
391    }
392
393    public ATNumber asNumber() throws InterpreterException {
394        throw new XTypeMismatch(ATNumber.class, this);
395    }
396
397    public ATMessage asMessage() throws InterpreterException {
398        throw new XTypeMismatch(ATMessage.class, this);
399    }
400
401    public ATField asField() throws InterpreterException {
402        throw new XTypeMismatch(ATField.class, this);
403    }
404
405    public ATMethod asMethod() throws InterpreterException {
406        throw new XTypeMismatch(ATMethod.class, this);
407    }
408
409    public ATHandler asHandler() throws InterpreterException {
410    	    throw new XTypeMismatch(ATHandler.class, this);
411    }
412
413    public ATTypeTag asTypeTag() throws InterpreterException {
414	    throw new XTypeMismatch(ATTypeTag.class, this);
415    }
416    
417    // Conversions for concurrency and distribution related object
418    public boolean isFarReference() {
419    	return false;
420    }
421    
422    public ATFarReference asFarReference() throws InterpreterException {
423  	    throw new XTypeMismatch(ATFarReference.class, this);
424  	}
425    
426    public ATAsyncMessage asAsyncMessage() throws InterpreterException {
427  	    throw new XTypeMismatch(ATAsyncMessage.class, this);
428  	}
429    
430    public ATActorMirror asActorMirror() throws InterpreterException {
431    	throw new XTypeMismatch(ATActorMirror.class, this);
432    }
433    
434    // Conversions for abstract grammar elements
435
436    public ATStatement asStatement() throws InterpreterException {
437        throw new XTypeMismatch(ATStatement.class, this);
438    }
439
440    public ATDefinition asDefinition() throws InterpreterException {
441        throw new XTypeMismatch(ATDefinition.class, this);
442    }
443
444    public ATExpression asExpression() throws InterpreterException {
445        return this;
446    }
447
448    public ATBegin asBegin() throws InterpreterException {
449        throw new XTypeMismatch(ATBegin.class, this);
450    }
451
452    public ATMessageCreation asMessageCreation() throws InterpreterException {
453        throw new XTypeMismatch(ATMessageCreation.class, this);
454    }
455
456    public ATUnquoteSplice asUnquoteSplice() throws InterpreterException {
457        throw new XTypeMismatch(ATUnquoteSplice.class, this);
458    }
459
460    public ATAssignVariable asVariableAssignment() throws InterpreterException {
461        throw new XTypeMismatch(ATAssignVariable.class, this);
462    }
463    
464    public ATSplice asSplice() throws InterpreterException {
465        throw new XTypeMismatch(ATSplice.class, this);
466    }
467    
468    // Conversions for native values
469    public NATObject asAmbientTalkObject() throws XTypeMismatch {
470    	throw new XTypeMismatch(NATObject.class, this);
471    }
472
473    public NATMirage asMirage() throws XTypeMismatch {
474    	throw new XTypeMismatch(NATMirage.class, this);
475    }
476
477    public NATNumber asNativeNumber() throws XTypeMismatch {
478        throw new XTypeMismatch(NATNumber.class, this);
479    }
480
481    public NATFraction asNativeFraction() throws XTypeMismatch {
482        throw new XTypeMismatch(NATFraction.class, this);
483    }
484
485    public NATText asNativeText() throws XTypeMismatch {
486    	throw new XTypeMismatch(NATText.class, this);
487    }
488
489    public NATTable asNativeTable() throws XTypeMismatch {
490        throw new XTypeMismatch(NATTable.class, this);
491    }
492
493    public NATBoolean asNativeBoolean() throws XTypeMismatch {
494        throw new XTypeMismatch(NATBoolean.class, this);
495    }
496    
497    public NATNumeric asNativeNumeric() throws XTypeMismatch {
498        throw new XTypeMismatch(NATNumeric.class, this);
499    }
500    
501    public NATFarReference asNativeFarReference() throws XTypeMismatch {
502    	throw new XTypeMismatch(NATFarReference.class, this);
503    }
504
505    public JavaObject asJavaObjectUnderSymbiosis() throws XTypeMismatch {
506    	    throw new XTypeMismatch(JavaObject.class, this);
507    }
508    
509    public JavaClass asJavaClassUnderSymbiosis() throws XTypeMismatch {
510	    throw new XTypeMismatch(JavaClass.class, this);
511    }
512    
513    /**
514     * Only true objects have a dynamic pointer, native objects denote 'nil' to
515     * be their dynamic parent when asked for it. Note that, for native objects,
516     * 'super' is a read-only field (i.e. there is no base_setSuper).
517     */
518    public ATObject base_getSuper() throws InterpreterException {
519        return NATNil._INSTANCE_;
520    };
521
522    public String toString() {
523        return Evaluator.toString(this);
524    }
525    
526    /**
527     * Java method invocations of equals are transformed into
528     * AmbientTalk '==' method invocations.
529     */
530	public boolean equals(Object other) {
531		try {
532			if (other instanceof ATObject) {
533				return this.base__opeql__opeql_((ATObject) other).asNativeBoolean().javaValue;
534			} else if (other instanceof SymbioticATObjectMarker) {
535				return this.base__opeql__opeql_(
536						((SymbioticATObjectMarker) other)._returnNativeAmbientTalkObject()).asNativeBoolean().javaValue;
537			}
538		} catch (InterpreterException e) {
539			Logging.Actor_LOG.warn("Error during equality testing:", e);
540		}
541		return false; 
542	}
543    
544	/**
545	 * By default, two AmbientTalk objects are equal if they are the
546	 * same object, or one is a proxy for the same object.
547	 */
548    public ATBoolean base__opeql__opeql_(ATObject other) throws InterpreterException {
549		// by default, ATObjects use pointer equality
550		return NATBoolean.atValue(this == other);
551    }
552    
553    public ATObject base_new(ATObject[] initargs) throws InterpreterException {
554    	return this.meta_newInstance(NATTable.atValue(initargs));
555    }
556    
557    public ATObject base_init(ATObject[] initargs) throws InterpreterException {
558    	return NATNil._INSTANCE_;
559    }
560
561	public ATBoolean meta_isCloneOf(ATObject original) throws InterpreterException {
562		return NATBoolean.atValue(
563				this.getClass() == original.getClass());
564	}
565
566	public ATBoolean meta_isRelatedTo(ATObject object) throws InterpreterException {
567		return this.meta_isCloneOf(object);
568	}
569	
570    /* ---------------------------------
571     * -- Type Testing and Querying --
572     * --------------------------------- */
573	
574    /**
575     * Native objects implement the type test non-recursively: only the type tags
576     * returned by {@link this#meta_getTypeTags()} are tested against.
577     */
578    public ATBoolean meta_isTaggedAs(ATTypeTag type) throws InterpreterException {
579    	ATObject[] types = this.meta_getTypeTags().asNativeTable().elements_;
580    	for (int i = 0; i < types.length; i++) {
581			if (types[i].asTypeTag().base_isSubtypeOf(type).asNativeBoolean().javaValue) {
582				return NATBoolean._TRUE_;
583			}
584		}
585    	return NATBoolean._FALSE_;
586    }
587    
588    /**
589     * By default, a native object (and also nil) has no type tags.
590     */
591    public ATTable meta_getTypeTags() throws InterpreterException {
592    	return NATTable.EMPTY;
593    }
594	
595    /* -----------------------------
596     * -- Object Passing protocol --
597     * ----------------------------- */
598
599    /**
600     * This method allows objects to decide which object should be serialized in their
601     * stead when they are passed as argument in an asynchronous message send that
602     * crosses actor boundaries. By default, nil decides that it is safe to serialize
603     * the object itself. Special objects such as e.g. closures should override this
604     * method and return a far reference encoding instead.
605     */
606    public ATObject meta_pass() throws InterpreterException {
607    	return this;
608    }
609    
610    /**
611     * After deserialization, ensure that nil remains unique.
612     */
613    public ATObject meta_resolve() throws InterpreterException {
614    	return NATNil._INSTANCE_;
615    }
616	
617	/**
618	 * Delegate the responsibility of serialization to the AT/2 meta-level 
619	 */
620	public Object writeReplace() throws ObjectStreamException {
621		try {
622			return this.meta_pass();
623		} catch(InterpreterException e) {
624			throw new InvalidObjectException("Failed to pass object " + this + ": " + e.getMessage());
625		}
626	}
627    
628	/**
629	 * Delegate the responsibility of deserialization to the AT/2 meta-level 
630	 */
631	public Object readResolve() throws ObjectStreamException {
632		try {
633			return this.meta_resolve();
634		} catch(InterpreterException e) {
635			throw new SerializationException(e);
636		}
637	}
638
639}