PageRenderTime 57ms CodeModel.GetById 27ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

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

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