PageRenderTime 82ms CodeModel.GetById 15ms app.highlight 58ms RepoModel.GetById 2ms app.codeStats 0ms

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

http://ambienttalk.googlecode.com/
Java | 992 lines | 275 code | 92 blank | 625 comment | 8 complexity | ce2518522c49f5d35d5e1fddff939ba6 MD5 | raw file
  1/**
  2 * AmbientTalk/2 Project
  3 * OBJLexicalRoot.java created on 8-aug-2006 at 16:51:10
  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.ATFarReference;
 32import edu.vub.at.actors.natives.ELActor;
 33import edu.vub.at.actors.natives.ELVirtualMachine;
 34import edu.vub.at.actors.natives.NATActorMirror;
 35import edu.vub.at.actors.natives.NATFarReference;
 36import edu.vub.at.actors.natives.Packet;
 37import edu.vub.at.actors.net.OBJNetwork;
 38import edu.vub.at.eval.Evaluator;
 39import edu.vub.at.exceptions.InterpreterException;
 40import edu.vub.at.exceptions.XAmbienttalk;
 41import edu.vub.at.objects.ATAbstractGrammar;
 42import edu.vub.at.objects.ATBoolean;
 43import edu.vub.at.objects.ATClosure;
 44import edu.vub.at.objects.ATHandler;
 45import edu.vub.at.objects.ATMethod;
 46import edu.vub.at.objects.ATNil;
 47import edu.vub.at.objects.ATNumber;
 48import edu.vub.at.objects.ATObject;
 49import edu.vub.at.objects.ATStripe;
 50import edu.vub.at.objects.ATTable;
 51import edu.vub.at.objects.ATText;
 52import edu.vub.at.objects.coercion.NativeStripes;
 53import edu.vub.at.objects.mirrors.NATMirage;
 54import edu.vub.at.objects.mirrors.OBJMirrorRoot;
 55import edu.vub.at.objects.symbiosis.JavaObject;
 56import edu.vub.at.objects.symbiosis.XJavaException;
 57import edu.vub.at.parser.NATParser;
 58
 59/**
 60 * An instance of the class OBJLexicalRoot represents the lexical root of an actor.
 61 * Since a lexical root is sealed (it cannot be modified) and contains no mutable fields,
 62 * it should be possible to share a singleton instance of this class among all actors.
 63 * 
 64 * The lexical root is an object containing globally visible AmbientTalk native methods.
 65 * Such methods include control structures such as if:then:else: and while:do:
 66 * but also object creation methods like object: and extend:with:
 67 * 
 68 * Furthermore, the lexical root is also responsible for ending recursive meta-level methods
 69 * such as lookup and assignField.
 70 * 
 71 * OBJLexicalRoot extends NATNil such that it inherits that class's ATObject protocol
 72 * to convert AmbientTalk invocations of a method m into Java base_m invocations.
 73 * 
 74 * Note that OBJLexicalRoot is a 'sentinel' class. The actual object bound to the
 75 * lexical root of an actor will be a normal NATObject which is assumed to be 'nested' in this instance.
 76 * This empty object is local to each actor and is mutable.
 77 * 
 78 * @author smostinc
 79 * @author tvcutsem
 80 */
 81public final class OBJLexicalRoot extends NATByCopy {
 82	
 83	/**
 84	 * The singleton instance of the sentinel lexical root
 85	 */
 86	static public final OBJLexicalRoot _INSTANCE_ = new OBJLexicalRoot();
 87	
 88	/**
 89	 * Constructor made private for singleton design pattern
 90	 */
 91	private OBJLexicalRoot() { }
 92	
 93	/* -----------------------
 94	 * -- Primitive Methods --
 95	 * ----------------------- */
 96	
 97	/* ===============================================================================
 98	 * NOTE: the code below has been replaced by dedicated syntax and AST elements.
 99	 * However, the skeleton of this code may still prove useful in the future, if
100	 * we ever plan to implement all base_ native methods as true AmbientTalk methods
101	 * (i.e. as PrimitiveMethod instances).
102	 * ===============================================================================
103	 */
104	
105	
106	/*
107	private static final AGSymbol _IMPORT_NAME_ = AGSymbol.jAlloc("import:");
108	private static final AGSymbol _IMPORT_ALIAS_NAME_ = AGSymbol.jAlloc("import:alias:");
109	private static final AGSymbol _IMPORT_EXCLUDE_NAME_ = AGSymbol.jAlloc("import:exclude:");
110	private static final AGSymbol _IMPORT_ALIAS_EXCLUDE_NAME_ = AGSymbol.jAlloc("import:alias:exclude:");
111	
112	private static final AGSymbol _SRC_PARAM_ = AGSymbol.jAlloc("sourceObject");
113	private static final AGSymbol _ALIAS_PARAM_ = AGSymbol.jAlloc("aliases");
114	private static final AGSymbol _EXCLUDE_PARAM_ = AGSymbol.jAlloc("exclude");
115	*/
116	
117	
118	/*protected static final PrimitiveMethod _PRIM_IMPORT_ = new PrimitiveMethod(_IMPORT_NAME_, NATTable.atValue(new ATObject[] { _SRC_PARAM_ })) {
119		public ATObject base_apply(ATTable arguments, ATContext ctx) throws InterpreterException {
120			  ATObject sourceObject = arguments.base_at(NATNumber.ONE);
121			  return performImport(sourceObject, ctx, new Hashtable(), OBJLexicalRoot.getDefaultExcludedSlots());
122		}
123	};*/
124	
125	/**
126	 * def import: sourceObject alias: [ `oldname -> `newname , ... ]
127	 */
128	/*protected static final PrimitiveMethod _PRIM_IMPORT_ALIAS_ = new PrimitiveMethod(_IMPORT_ALIAS_NAME_, NATTable.atValue(new ATObject[] { _SRC_PARAM_, _ALIAS_PARAM_ })) {
129		public ATObject base_apply(ATTable arguments, ATContext ctx) throws InterpreterException {
130			  ATObject sourceObject = arguments.base_at(NATNumber.ONE);
131			  ATObject aliases = arguments.base_at(NATNumber.atValue(2));
132			  return performImport(sourceObject, ctx, preprocessAliases(aliases.base_asTable()), OBJLexicalRoot.getDefaultExcludedSlots());
133		}
134	};*/
135	
136	/**
137	 * def import: sourceObject excludes: [ `name1, `name2, ... ]
138	 */
139	/*protected static final PrimitiveMethod _PRIM_IMPORT_EXCLUDE_ = new PrimitiveMethod(_IMPORT_EXCLUDE_NAME_, NATTable.atValue(new ATObject[] { _SRC_PARAM_, _EXCLUDE_PARAM_ })) {
140		public ATObject base_apply(ATTable arguments, ATContext ctx) throws InterpreterException {
141			  ATObject sourceObject = arguments.base_at(NATNumber.ONE);
142			  ATObject exclusions = arguments.base_at(NATNumber.atValue(2));
143			  return performImport(sourceObject, ctx, new Hashtable(), preprocessExcludes(exclusions.base_asTable()));
144		}
145	};*/
146	
147	/**
148	 * def import: sourceObject alias: [ `oldname -> `newname, ... ] excludes: [ `name1, `name2, ... ]
149	 */
150	/*protected static final PrimitiveMethod _PRIM_IMPORT_ALIAS_EXCLUDE_ = new PrimitiveMethod(_IMPORT_ALIAS_EXCLUDE_NAME_,
151			                                                                                 NATTable.atValue(new ATObject[] { _SRC_PARAM_, _ALIAS_PARAM_, _EXCLUDE_PARAM_ })) {
152		public ATObject base_apply(ATTable arguments, ATContext ctx) throws InterpreterException {
153			  ATObject sourceObject = arguments.base_at(NATNumber.ONE);
154			  ATObject aliases = arguments.base_at(NATNumber.atValue(2));
155			  ATObject exclusions = arguments.base_at(NATNumber.atValue(3));
156			  return performImport(sourceObject, ctx, preprocessAliases(aliases.base_asTable()), preprocessExcludes(exclusions.base_asTable()));
157		}
158	};*/
159	
160	/**
161	 * Invoked whenever a new true AmbientTalk object is created that should
162	 * represent the root. This gives the lexical root a chance to install its
163	 * primitive methods.
164	 */
165	/*public static void initializeRoot(NATObject root) {
166		try {
167			// add import: native
168			root.meta_addMethod(_PRIM_IMPORT_);
169			// add import:alias: native
170			root.meta_addMethod(_PRIM_IMPORT_ALIAS_);
171			// add import:exclude: native
172			root.meta_addMethod(_PRIM_IMPORT_EXCLUDE_);
173			// add import:alias:exclude: native
174			root.meta_addMethod(_PRIM_IMPORT_ALIAS_EXCLUDE_);
175		} catch (InterpreterException e) {
176			Logging.Init_LOG.fatal("Failed to initialize the root!", e);
177		}
178	}*/
179	
180	/* ----------------------
181	 * -- Global variables --
182	 * ---------------------- */
183	
184	/**
185	 * nil
186	 */
187	public ATNil base_getNil() {
188		return NATNil._INSTANCE_;
189	}
190	
191	/**
192	 * true
193	 */
194	public ATBoolean base_getTrue() {
195		return NATBoolean._TRUE_;
196	}
197	
198	/**
199	 * false
200	 */
201	public ATBoolean base_getFalse() {
202		return NATBoolean._FALSE_;
203	}
204	
205	/**
206	 * '/' (the global namespace)
207	 * '/' is an alias for 'lobby'
208	 */
209	public ATObject base_get_opdiv_() {
210		return base_getLobby();
211	}
212	
213	/**
214	 * lobby (the global namespace initialized using the objectpath)
215	 */
216	public ATObject base_getLobby() {
217		return Evaluator.getLobbyNamespace();
218	}
219	
220	/**
221	 * root (the global scope)
222	 */
223	public ATObject base_getRoot() {
224		return Evaluator.getGlobalLexicalScope();
225	}
226	
227	/**
228	 * jlobby (the Java class package root, initialized using the Java classpath)
229	 */
230	public ATObject base_getJlobby() {
231		return Evaluator.getJLobbyRoot();
232	}
233
234	/**
235	 * network (the network control object, to go online and offline)
236	 */
237	public ATObject base_getNetwork() {
238		return OBJNetwork._INSTANCE_;
239	}
240	
241	/**
242	 * defaultMirror (the default mirror on objects)
243	 */
244	public ATObject base_getDefaultMirror() {
245		return Evaluator.getMirrorRoot();
246	}
247	
248	/* ------------------------
249	 * -- Control Structures --
250	 * ------------------------ */
251	
252	/**
253	 * The if:then: primitive, which calls back on the boolean using ifTrue:
254	 * 
255	 * usage:
256	 *  if: booleanCondition then: { consequent }
257	 * 
258	 * @param cond a boolean object
259	 * @param consequent a closure containing the code to execute if the boolean is true
260	 * @return the result of invoking booleanCondition.ifTrue: { consequent }
261	 * @throws InterpreterException if raised inside the consequent closure.
262	 */
263	public ATObject base_if_then_(ATBoolean cond, ATClosure consequent) throws InterpreterException {
264		return cond.base_ifTrue_(consequent);
265	}
266	
267	/**
268	 * The if:then:else primitive, which calls back on the boolean using ifTrue:ifFalse:
269	 * 
270	 * usage:
271	 *  if: booleanCondition then: { consequent } else: { alternative }
272	 * 
273	 * pseudo-implementation:
274	 *  booleanCondition.ifTrue: { consequent } ifFalse: { alternative }
275	 * 
276	 * @param cond a boolean object
277	 * @param consequent a closure containing the code to execute if the boolean is true
278	 * @param alternative a closure containing the code to execute if the boolean is false
279	 * @return the result of invoking booleanCondition.ifTrue: { consequent }
280	 * @throws InterpreterException if raised inside the consequent or alternative closure.
281	 */
282	public ATObject base_if_then_else_(ATBoolean cond, ATClosure consequent, ATClosure alternative) throws InterpreterException {
283		return cond.base_ifTrue_ifFalse_(consequent, alternative);
284	}
285	
286	/**
287	 * The while:do: primitive, which calls back on the closure using whileTrue:
288	 * 
289	 * usage:
290	 *  while: { condition } do: { body }
291	 * 
292	 * pseudo-implementation:
293	 *  { condition }.whileTrue: { body }
294	 * 
295	 * @param condition a closure expected to return a boolean object
296	 * @param body a closure containing the code to execute as long as the condition closure returns true
297	 * @return the result of invoking { body }.whileTrue: { condition }
298	 * @throws InterpreterException if raised inside the condition or body closures.
299	 */
300	public ATObject base_while_do_(ATClosure condition, ATClosure body) throws InterpreterException {
301		return condition.base_whileTrue_(body);
302	}
303	
304	/**
305	 * The foreach:in: primitive, which calls back on the table using each:
306	 * 
307	 * usage:
308	 *  foreach: { |v| body } in: [ table ]
309	 * 
310	 * pseudo-implementation:
311	 *  [ table ].each: { |v| body }
312	 * 
313	 * @param body a closure expected to take one argument to be applied to each element of the table
314	 * @param tab a table to apply the iterator block to
315	 * @return the result of invoking [ table ].each: { |v| body }
316	 * @throws InterpreterException if raised inside the iterator block.
317	 */
318	public ATObject base_foreach_in_(ATClosure body, ATTable tab) throws InterpreterException {
319		return tab.base_each_(body);
320	}
321
322	/**
323	 * The do:if: primitive, which in Ruby terminology is a 'statement modifier'
324	 * 
325	 * usage:
326	 *  do: { body } if: condition
327	 * 
328	 * pseudo-implementation:
329	 *  condition.ifTrue: { body }
330	 * 
331	 * @param body a zero-argument closure to execute if the condition is true
332	 * @param condition a boolean expression
333	 * @return the result of invoking body if the condition is true or nil if the condition is false
334	 * @throws InterpreterException if raised inside the body block.
335	 */
336	public ATObject base_do_if_(ATClosure body, ATBoolean condition) throws InterpreterException {
337		return condition.base_ifTrue_(body);
338	}
339	
340	/**
341	 * The do:unless: primitive, which in Ruby terminology is a 'statement modifier'
342	 * 
343	 * usage:
344	 *  do: { body } unless: condition
345	 * 
346	 * pseudo-implementation:
347	 *  condition.ifFalse: { body }
348	 * 
349	 * @param body a zero-argument closure to execute if the condition is false
350	 * @param condition a boolean expression
351	 * @return the result of invoking body if the condition is false or nil if the condition is true
352	 * @throws InterpreterException if raised inside the body block.
353	 */
354	public ATObject base_do_unless_(ATClosure body, ATBoolean condition) throws InterpreterException {
355		return condition.base_ifFalse_(body);
356	}
357	
358	/**
359	 * The let: primitive, which allows for the easy creation of temporary local variables.
360	 * This primitive should be used in conjunction with a closure that declares optional
361	 * parameters. Because the closure will be invoked with zero arguments, all of the
362	 * parameters will be given their corresponding default initial value. The parameters
363	 * are defined local to the closure's body.
364	 * 
365	 * Note: this let behaves like Scheme's let* and letrec, i.e. the following is legal:
366	 * let: { |var1 := value1, var2 := var1, var3 := { ... var3() ... } | ... }
367	 * 
368	 * usage:
369	 *  let: { |var := value| body }
370	 * 
371	 * pseudo-implementation:
372	 *  def let: closure { closure() }
373	 * 
374	 * @param body a closure which is supposed to declare some optional parameters
375	 * @return the result of invoking the body closure
376	 * @throws InterpreterException if raised inside the body block.
377	 */
378	public ATObject base_let_(ATClosure body) throws InterpreterException {
379		return body.base_apply(NATTable.EMPTY);
380	}
381	
382	/* ------------------------------------------
383	 * -- Actor Creation and accessing Methods --
384	 * ------------------------------------------ */
385	
386	/**
387	 * actor: { code }
388	 *  == actor: { code } mirroredBy: <default actor mirror>
389	 *  
390	 * The semantics of actor creation is as follows:
391	 * - Mandatory parameters to the block of initialization code are treated as lexically visible
392	 *   variables that have to remain available in the new actor behaviour. Hence, these variables
393	 *   are evaluated to values immediately at creation-time and parameter-passed to the new actor.
394	 * - The closure containing the initialization code is unpacked, its lexical scope is disregarded
395	 *   and the unwrapped method is serialized and sent to the new actor, which can use it to
396	 *   initialize his behaviour object.
397	 * - The creating actor waits for the created actor to spawn a new behaviour and to return a far
398	 *   reference to this behaviour. From that point on, the creating actor can run in parallel with
399	 *   the created actor, which only then evaluates the initialization code to initialize its behaviour.
400	 *  
401	 */
402	public ATObject base_actor_(ATClosure code) throws InterpreterException {
403		ATMethod method = code.base_getMethod();
404		NATTable copiedBindings = Evaluator.evalMandatoryPars(
405				method.base_getParameters(),
406				code.base_getContext());
407		
408		Packet serializedBindings = new Packet("actor-bindings", copiedBindings);
409		Packet serializedInitCode = new Packet("actor-initcode", method);
410		ELVirtualMachine host = ELVirtualMachine.currentVM();
411		return NATActorMirror.createActor(host, serializedBindings, serializedInitCode, new NATActorMirror(host));
412	}
413	
414	/**
415	 * actor => a reference to a mirror on the current actor
416	 */
417	public ATActorMirror base_getActor() throws InterpreterException {
418		return ELActor.currentActor().getActorMirror();
419	}
420	
421	/**
422	 * export: object as: topic
423	 *  => object becomes discoverable by objects in other actors via topic
424	 * returns a publication object that can be used to cancel the export
425	 */
426	public ATObject base_export_as_(ATObject object, ATStripe topic) throws InterpreterException {
427		return ELActor.currentActor().getActorMirror().base_provide(topic, object);
428	}
429	
430	/**
431	 * when: topic discovered: { code }
432	 *  => when an object is exported by another actor under topic, trigger the code
433	 * returns a subscription object that can be used to cancel the handler
434	 * 
435	 * Once the code block has run once, it will not be triggered again.
436	 */
437	public ATObject base_when_discovered_(ATStripe topic, ATClosure handler) throws InterpreterException {
438		return ELActor.currentActor().getActorMirror().base_require(topic, handler, NATBoolean._FALSE_);
439	}
440	
441	/**
442	 * whenever: topic discovered: { code }
443	 *  => when an object is exported by another actor under topic, trigger the code
444	 * returns a subscription object that can be used to cancel the handler
445	 * 
446	 * The code block can be fired multiple times. To stop the block from triggering upon
447	 * new publications, it must be explicitly cancelled
448	 */
449	public ATObject base_whenever_discovered_(ATStripe topic, ATClosure handler) throws InterpreterException {
450		return ELActor.currentActor().getActorMirror().base_require(topic, handler, NATBoolean._TRUE_);
451	}
452	
453	/**
454	 * when: farReference disconnected: { code }
455	 *  => when the remote reference is broken due to network disconnections, trigger the code
456	 * returns a subscription object that can be used to cancel the listener
457	 * 
458	 * The code of block will be also fired when the object referenced is taken offline.
459	 */
460	public ATObject base_when_disconnected_(ATFarReference farReference, ATClosure listener) throws InterpreterException {
461		farReference.asNativeFarReference().addDisconnectionListener(listener);
462		return new NATFarReference.NATDisconnectionSubscription(farReference.asNativeFarReference(), listener);
463	}
464	
465	/**
466	 * when: farReference reconnected: { code }
467	 *  => when the remote reference is reinstated after a network disconnection, trigger the code
468	 * returns a subscription object that can be used to cancel the listener
469	 */
470	public ATObject base_when_reconnected_(ATFarReference farReference, ATClosure listener) throws InterpreterException {
471		farReference.asNativeFarReference().addReconnectionListener(listener);
472		return new NATFarReference.NATReconnectionSubscription(farReference.asNativeFarReference(), listener);
473	}
474	
475	/**
476	 * when: farReference expired: { code }
477	 *  => when the (remote/local) reference is broken because the object referenced expired ( i.e. it was 
478	 *  taken offline), trigger the code returns a subscription object that can be used to cancel the listener
479	 */
480	public ATObject base_when_expired_(ATFarReference farReference, ATClosure listener) throws InterpreterException {
481		farReference.asNativeFarReference().addExpiredListener(listener);
482		return new NATFarReference.NATExpiredSubscription(farReference.asNativeFarReference(), listener);
483	}
484	
485
486	/**
487	 * retract: farReference 
488	 *  => retract all currently unsent messages from the far reference's outbox
489	 *  This has the side effect that the returned messages will *not* be sent automatically anymore,
490	 *  the programmer is responsible to resend all messages that still need to be sent by hand.
491	 *  
492	 *  Note that the returned messages are copies of the original.
493	 * @return a table with a copy of all the messages being sent.
494	 */
495	public ATTable base_retract_(ATFarReference farReference) throws InterpreterException {
496		return farReference.meta_retractUnsentMessages();
497	}
498	
499	/* -----------------------------
500	 * -- Object Creation Methods --
501	 * ----------------------------- */
502	
503	/**
504	 * The object: primitive, implemented as base-level code.
505	 * object: expects to be passed a closure such that it can extract the correct
506	 * scope to be used as the object's lexical parent.
507	 * 
508	 * usage:
509	 *  object: { someCode }
510	 *  
511	 * pseudo-implementation:
512	 *  { def obj := objectP.new(mirrorOf(someCode).context.lexicalScope);
513	 *    mirrorOf(someCode).method.body.eval(contextP.new(obj, obj, nil));
514	 *    obj }
515	 *  = object: { someCode } childOf: nil extends: false stripedWith: [] mirroredBy: mirrorroot
516	 * 
517	 * The code block used to initialize the object may contain formal parameters.
518	 * If this is the case, the formals are evaluated in the context of the lexical scope
519	 * of the code block to values. These values are then bound to the formal parameters
520	 * in the object itself. This is primarily useful for copying surrounding variables
521	 * within the object, e.g. for isolates which lose access to their surrounding scope.
522	 * 
523	 * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent
524	 * @return a new object whose dynamic parent is NIL, whose lexical parent is the closure's lexical scope, initialized by the closure's code
525	 * @throws InterpreterException if raised inside the code closure.
526	 */
527	public ATObject base_object_(ATClosure code) throws InterpreterException {
528		// TODO: delegate to actor mirror?
529		return base_object_childOf_extends_stripedWith_mirroredBy_(code, NATNil._INSTANCE_, NATBoolean._FALSE_ /* SHARES-A link */, NATTable.EMPTY, base_getDefaultMirror());
530	}
531	
532	/**
533	 * The extend:with: primitive, which delegates to the extend meta operation on the parent object. 
534	 * 
535	 * usage:
536	 *  extend: anObject with: { someCode }
537	 * 
538	 * pseudo-implementation:
539	 *  = object: { someCode } childOf: anObject extends: true stripedWith: [] mirroredBy: mirrorroot
540	 *  
541	 * @param parent the object to extend
542	 * @param code a closure containing the code to extend the parent object with
543	 * @return an object whose dynamic parent is an is-a link to the parent parameter
544	 * @throws InterpreterException if raised inside the code closure.
545	 */
546	public ATObject base_extend_with_(ATObject parent, ATClosure code) throws InterpreterException {
547		// TODO: delegate to actor mirror?
548		return base_object_childOf_extends_stripedWith_mirroredBy_(code, parent, NATBoolean._TRUE_ /* IS-A link */, NATTable.EMPTY, base_getDefaultMirror());
549	}
550	
551	public ATObject base_extend_with_stripedWith_(ATObject parent, ATClosure code, ATTable stripes) throws InterpreterException {
552		// TODO: delegate to actor mirror?
553		return base_object_childOf_extends_stripedWith_mirroredBy_(code, parent, NATBoolean._TRUE_ /* IS-A link */, stripes, base_getDefaultMirror());
554	}
555	
556	public ATObject base_extend_with_mirroredBy_(ATObject parent, ATClosure code, ATObject mirror) throws InterpreterException {
557		// TODO: delegate to actor mirror?
558		return base_object_childOf_extends_stripedWith_mirroredBy_(code, parent, NATBoolean._TRUE_ /* IS-A link */, NATTable.EMPTY, mirror);
559	}
560	
561	public ATObject base_extend_with_stripedWith_mirroredBy_(ATObject parent, ATClosure code, ATTable stripes, ATObject mirror) throws InterpreterException {
562		// TODO: delegate to actor mirror?
563		return base_object_childOf_extends_stripedWith_mirroredBy_(code, parent, NATBoolean._TRUE_ /* IS-A link */, stripes, mirror);
564	}
565	
566	/**
567	 * The share:with: primitive, which delegates to the share meta operation on the parent object. 
568	 * 
569	 * usage:
570	 *  share: anObject with: { someCode }
571	 * 
572	 * pseudo-implementation:
573	 *  = object: { someCode } childOf: anObject extends: false stripedWith: [] mirroredBy: mirrorroot
574	 * 
575	 * @param parent the object to extend
576	 * @param code a closure containing the code to extend the parent object with
577	 * @return an object whose dynamic parent is a shares-a link to the parent parameter
578	 * @throws InterpreterException if raised inside the code closure.
579	 */
580	public ATObject base_share_with_(ATObject parent, ATClosure code) throws InterpreterException {
581		// TODO: delegate to actor mirror?
582		return base_object_childOf_extends_stripedWith_mirroredBy_(code, parent, NATBoolean._FALSE_ /* SHARES-A link */, NATTable.EMPTY, base_getDefaultMirror());
583	}
584
585	public ATObject base_share_with_stripedWith_(ATObject parent, ATClosure code, ATTable stripes) throws InterpreterException {
586		// TODO: delegate to actor mirror?
587		return base_object_childOf_extends_stripedWith_mirroredBy_(code, parent, NATBoolean._FALSE_ /* SHARES-A link */, stripes, base_getDefaultMirror());
588	}
589	
590	public ATObject base_share_with_mirroredBy_(ATObject parent, ATClosure code, ATObject mirror) throws InterpreterException {
591		// TODO: delegate to actor mirror?
592		return base_object_childOf_extends_stripedWith_mirroredBy_(code, parent, NATBoolean._FALSE_ /* SHARES-A link */, NATTable.EMPTY, mirror);
593	}
594	
595	public ATObject base_share_with_stripedWith_mirroredBy_(ATObject parent, ATClosure code, ATTable stripes, ATObject mirror) throws InterpreterException {
596		// TODO: delegate to actor mirror?
597		return base_object_childOf_extends_stripedWith_mirroredBy_(code, parent, NATBoolean._FALSE_ /* SHARES-A link */, stripes, mirror);
598	}
599	
600	/**
601	 * object: { code } stripedWith: [ s1, s2, ... ]
602	 * => creates a new object tagged with the given stripes
603	 * = object: { code } childOf: nil extends: false stripedWith: [ s1, s2, ... ] mirroredBy: mirrorroot
604	 */
605	public ATObject base_object_stripedWith_(ATClosure code, ATTable stripes) throws InterpreterException {
606		// TODO: delegate to actor mirror?
607		return base_object_childOf_extends_stripedWith_mirroredBy_(code, NATNil._INSTANCE_, NATBoolean._FALSE_ /* SHARES-A link */, stripes, base_getDefaultMirror());
608	}
609	
610	/**
611	 * isolate: { code }
612	 *  => create an isolate object
613	 *  
614	 * Equivalent to:
615	 *   object: { code } stripedWith: [ at.stripes.Isolate ]
616	 */
617	public ATObject base_isolate_(ATClosure code) throws InterpreterException {
618		return base_object_stripedWith_(code, NATTable.of(NativeStripes._ISOLATE_));
619	}
620	
621	/**
622	 * The mirror: primitive, which allows creating custom mirrors which can be used
623	 * to allow intercessive reflection on objects created from this mirror.
624	 * 
625	 * usage:
626	 *  mirror: { someCode } 
627	 * 
628	 * pseudo-implementation:
629	 *  = object: { code } childOf: mirrorroot extends: true stripedWith: [] mirroredBy: mirrorroot
630	 * 
631	 * @param code a closure containing both the code with which to initialize the mirror and the new mirror's lexical parent
632	 * @return a new mirror containing the specified definitions
633	 */
634	public ATObject base_mirror_(ATClosure code) throws InterpreterException {
635		// TODO: delegate to actor mirror?
636		return base_object_childOf_extends_stripedWith_mirroredBy_(code, base_getDefaultMirror(), NATBoolean._TRUE_ /* IS-A link */, NATTable.EMPTY, base_getDefaultMirror());
637	}
638	
639	/**
640	 * object: { code } mirroredBy: mirror
641	 *  => return an object mirage initialized with code
642	 *  = object: { code } childOf: nil extends: false stripedWith: [] mirroredBy: mirror
643	 */
644	public ATObject base_object_mirroredBy_(ATClosure code, ATObject mirror) throws InterpreterException {
645		// TODO: delegate to actor mirror?
646		return base_object_childOf_extends_stripedWith_mirroredBy_(code, NATNil._INSTANCE_, NATBoolean._FALSE_ /* SHARES-A link */, NATTable.EMPTY, mirror);
647	}
648	
649	/**
650	 * object: { code } stripedWith: [ s1, s2, ... ] mirroredBy: mirror
651	 *  => return an object mirage initialized with code and striped with the given stripes
652	 *  = object: { code } childOf: nil extends: false stripedWith: [s1, s2, ... ] mirroredBy: mirror
653	 */
654	public ATObject base_object_stripedWith_mirroredBy_(ATClosure code, ATTable stripes, ATObject mirror) throws InterpreterException {
655		// TODO: delegate to actor mirror?
656		return base_object_childOf_extends_stripedWith_mirroredBy_(code, NATNil._INSTANCE_, NATBoolean._FALSE_ /* SHARES-A link */, stripes, mirror);
657	}
658	
659	/**
660	 * object: { code } childOf: parent extends: parentType stripedWith: [ stripes ] mirroredBy: mirror
661	 *  => return a new object o initialized with code where:
662	 *   o.super == parent
663	 *   o.lexParent == code.lexScope
664	 *   o.parentType == parentType
665	 *   o.stripes == stripes
666	 *   (reflect: o) == mirror.new(o)
667	 *   
668	 * @param code the code with which to initialize the object + the object's lexical parent
669	 * @param parent the object that is to become the initial parent of the newly created object
670	 * @param parentType if true, the child has an IS-A relationship with the parent, SHARES-A otherwise
671	 * @param stripes the stripes with which the newly created object should be striped
672	 * @param mirror the custom mirror for this object, or mirrorroot for a default object
673	 * @return the new object, fully initialized with code
674	 */
675	public ATObject base_object_childOf_extends_stripedWith_mirroredBy_(ATClosure code, ATObject parent, ATBoolean parentType, ATTable stripes, ATObject mirror) throws InterpreterException {
676		ATStripe[] stripeArray = NATStripe.toStripeArray(stripes);
677		boolean parentRelation = parentType.asNativeBoolean().javaValue;
678		NATObject newObject;
679		// if the mirror is a 'default' mirror...
680		if (mirror instanceof OBJMirrorRoot) {
681			// then create a native object
682			newObject = new NATObject(parent, // dynamic parent
683					                  code.base_getContext().base_getLexicalScope(), // lexical parent
684					                  parentRelation, // IS-A or SHARES-A
685					                  stripeArray); // initial stripes
686		} else {
687			// else create a mirage mirrored by the custom mirror
688			newObject = NATMirage.createMirage(code, parent, parentRelation, stripeArray, mirror);
689		}
690		
691		newObject.initializeWithCode(code);
692		return newObject;
693	}
694	
695	/**
696	 * The reflect: primitive, which returns a mirror on an object.
697	 * 
698	 * usage:
699	 *  reflect: anObject
700	 * 
701	 * pseudo-implementation:
702	 *  at.mirrors.mirrorfactory.createMirror(anObject)
703	 * 
704	 * @param reflectee the object to reflect upon
705	 * @return a mirror reflecting the given object
706	 */
707	public ATObject base_reflect_(ATObject reflectee) throws InterpreterException {
708		return base_getActor().base_createMirror(reflectee);
709	}
710	
711	/**
712	 * The clone: primitive, which returns a clone of an object.
713	 * 
714	 * When a mirror is cloned, its base field is *shared* with the original mirror (because of
715	 * shallow copy semantics). However, the base object will still be tied to the original mirror.
716	 * Therefore, the clone: operator is implemented as follows:
717	 * 
718     * def clone: obj {
719     *   if: (is: obj stripedWith: Mirror) then: {
720     *     reflect: (clone: obj.base)
721     *   } else: {
722     *     (reflect: obj).clone()
723     *   }
724     * }
725	 * 
726	 * usage:
727	 *  clone: anObject
728	 * 
729	 * @param original the object to copy
730	 * @return a clone of the given object
731	 */
732	public ATObject base_clone_(ATObject original) throws InterpreterException {
733		if (original.meta_isStripedWith(NativeStripes._MIRROR_).asNativeBoolean().javaValue) {
734		    return base_reflect_(base_clone_(original.meta_select(original, OBJMirrorRoot._BASE_NAME_)));
735		} else {
736			return original.meta_clone();
737		}
738	}
739	
740	/**
741	 * takeOffline: obj 
742	 * => removes an object from the export table of an actor -i.e. the object is no longer 
743	 * remotely accessible.
744	 * @return NIL
745	 */
746	 public ATNil base_takeOffline_ (ATObject object) throws InterpreterException{
747		 
748		ELActor.currentActor().takeOffline(object);
749		return NATNil._INSTANCE_;
750	 }
751	
752	/* -------------------
753	 * -- Stripe Support -
754	 * ------------------- */
755	
756	/**
757	 * is: object stripedWith: stripe
758	 * => returns true if the given object is striped with the given stripe
759	 */
760	public ATBoolean base_is_stripedWith_(ATObject object, ATStripe stripe) throws InterpreterException {
761		return object.meta_isStripedWith(stripe);
762	}
763	
764	/**
765	 * stripesOf: object
766	 * => returns all of the stripes of an object
767	 */
768	public ATTable base_stripesOf_(ATObject object) throws InterpreterException {
769		return object.meta_getStripes();
770	}
771	
772	/* -------------------------------
773	 * -- Exception Handling Support -
774	 * ------------------------------- */
775	
776	/**
777	 * try: { tryBlock } usingHandlers: [ handler1, handler2, ... ]
778	 * 
779	 * Applies the given closure (to []) and handles exceptions using the given exception handlers.
780	 * This is the most general means of doing exception handling in AmbientTalk/2.
781	 * 
782	 * The handlers given in the handler table represent first-class handler objects, which should respond to the 'canHandle' message.
783	 */
784	public ATObject base_try_usingHandlers_(ATClosure tryBlock, ATTable exceptionHandlers) throws InterpreterException {
785		try {
786			return tryBlock.base_apply(NATTable.EMPTY);
787		} catch(InterpreterException e) {
788			ATObject[] handlers = exceptionHandlers.asNativeTable().elements_;
789			
790			// find the appropriate handler
791			for (int i = 0; i < handlers.length; i++) {
792				ATHandler handler = handlers[i].asHandler();
793				ATObject exc = e.getAmbientTalkRepresentation();
794				if (handler.base_canHandle(exc).asNativeBoolean().javaValue) {
795					return handler.base_handle(exc);
796				};	
797			}
798			
799			// no handler found, re-throw the exception
800			throw e;
801		}
802	}
803	
804	/**
805	 * try: { tryBlock} using: handler
806	 * 
807	 * Ad-hoc code for one exception handler
808	 */
809	public ATObject base_try_using_(ATClosure tryBlock, ATHandler handler) throws InterpreterException {
810		try {
811			return tryBlock.base_apply(NATTable.EMPTY);
812		} catch(InterpreterException e) {
813			ATObject exc = e.getAmbientTalkRepresentation();
814			if (handler.base_canHandle(exc).asNativeBoolean().javaValue) {
815				return handler.base_handle(exc);
816			} else {
817				throw e;
818			}
819		}
820	}
821	
822	/**
823	 * try: { tryBlock} using: handler1 using: handler2
824	 * 
825	 * Ad-hoc code for two exception handlers
826	 */
827	public ATObject base_try_using_using_(ATClosure tryBlock, ATHandler hdl1, ATHandler hdl2) throws InterpreterException {
828		return base_try_usingHandlers_(tryBlock, NATTable.atValue(new ATObject[] { hdl1, hdl2 }));
829	}
830	
831	/**
832	 * try: { tryBlock} using: hdl1 using: hdl2 using: hdl3
833	 * 
834	 * Ad-hoc code for three exception handlers
835	 */
836	public ATObject base_try_using_using_using_(ATClosure tryBlock, ATHandler hdl1, ATHandler hdl2, ATHandler hdl3) throws InterpreterException {
837		return base_try_usingHandlers_(tryBlock, NATTable.atValue(new ATObject[] { hdl1, hdl2, hdl3 }));
838	}
839	
840	/**
841	 * try: { tryBlock} catch: stripe using: { |e| replacementCode }
842	 * 
843	 * 'Syntactic sugar' for one in-line handler
844	 */
845	public ATObject base_try_catch_using_(ATClosure tryBlock, ATStripe filter, ATClosure replacementCode) throws InterpreterException {
846		return base_try_using_(tryBlock, new NATHandler(filter, replacementCode));
847	}
848	
849	/**
850	 * try: {
851	 *   tryBlock
852	 * } catch: stripe using: { |e|
853	 *   replacementCode
854	 * } catch: stripe2 using: { |e|
855	 *   replacementCode2
856	 * }
857	 * 
858	 * 'Syntactic sugar' for two in-line handlers
859	 */
860	public ATObject base_try_catch_using_catch_using_(	ATClosure tryBlock,
861													ATStripe filter1, ATClosure hdl1,
862			                						   	ATStripe filter2, ATClosure hdl2) throws InterpreterException {
863		return base_try_using_using_(tryBlock, new NATHandler(filter1, hdl1), new NATHandler(filter2, hdl2));
864	}
865	
866	/**
867	 * try: {
868	 *   tryBlock
869	 * } catch: stripe using: { |e|
870	 *   replacementCode
871	 * } catch: stripe2 using: { |e|
872	 *   replacementCode2
873	 * } catch: stripe3 using: { |e|
874	 *   replacementCode3
875	 * }
876	 * 
877	 * 'Syntactic sugar' for three in-line handlers
878	 */
879	public ATObject base_try_catch_using_catch_using_catch_using_(ATClosure tryBlock,
880															   ATStripe filter1, ATClosure hdl1,
881															   ATStripe filter2, ATClosure hdl2,
882															   ATStripe filter3, ATClosure hdl3) throws InterpreterException {
883		return base_try_using_using_using_(tryBlock, new NATHandler(filter1, hdl1), new NATHandler(filter2, hdl2), new NATHandler(filter3, hdl3));
884	}
885	
886	/**
887	 * handle: stripe with: { |e| replacementCode }
888	 * 
889	 * Creates a first-class handler from a filter prototype and some handler code.
890	 */
891	public ATObject base_handle_with_(ATStripe filter, ATClosure replacementCode) {
892		return new NATHandler(filter, replacementCode);
893	}
894	
895	/**
896	 * raise: exception
897	 * 
898	 * Raises an exception which can be caught by dynamically installed try-catch-using blocks.
899	 */
900	public ATNil base_raise_(ATObject anExceptionObject) throws InterpreterException {
901		throw Evaluator.asNativeException(anExceptionObject);
902	}
903	
904	/* --------------------
905	 * -- Unary Operators -
906	 * -------------------- */
907	
908	/**
909	 * The unary ! primitive:
910	 * !b == b.not()
911	 */
912	public ATBoolean base__opnot_(ATBoolean b) throws InterpreterException {
913		return b.base_not();
914	}
915	
916	/**
917	 * The unary - primitive:
918	 * -NBR(n) == NBR(-n)
919	 */
920	public ATNumber base__opmns_(ATNumber n) throws InterpreterException {
921		return NATNumber.atValue(- n.asNativeNumber().javaValue);
922	}
923	
924	/**
925	 * The unary + primitive:
926	 * +NBR(n) == NBR(n)
927	 */
928	public ATNumber base__oppls_(ATNumber n) throws InterpreterException {
929		return n;
930	}
931	
932	/* -------------------
933	 * -- Miscellaneous --
934	 * ------------------- */
935	
936	/**
937	 * read: "text" => parses the given string into an AST
938	 */
939	public ATAbstractGrammar base_read_(ATText source) throws InterpreterException {
940		return NATParser._INSTANCE_.base_parse(source);
941	}
942	
943	/**
944	 * eval: ast in: obj => evaluates the given AST in the context of the given object, returning its value
945	 */
946	public ATObject base_eval_in_(ATAbstractGrammar ast, ATObject obj) throws InterpreterException {
947		return ast.meta_eval(new NATContext(obj, obj));
948	}
949
950	/**
951	 * print: expression => string representing the expression
952	 */
953	public ATText base_print_(ATObject obj) throws InterpreterException {
954		return obj.meta_print();
955	}
956	
957	/**
958	 * custom implementation of the default object methods == and new
959	 * the reason for this custom implementation: during the execution
960	 * of these methods, 'this' should refer to the global lexical scope object (the root),
961	 * not to the OBJLexicalRoot instance.
962	 * hence, when invoking one of these methods lexically, the receiver is always 'root'
963	 * For example, "==(obj)" is equivalent to "root == obj" (or "root.==(obj)")
964	 */
965    public ATBoolean base__opeql__opeql_(ATObject comparand) throws InterpreterException {
966        return Evaluator.getGlobalLexicalScope().base__opeql__opeql_(comparand);
967    }
968	
969    /**
970     * Invoking root.new(args) results in an exception for reasons of safety.
971     * We could also have opted to simply return 'root' (i.e. make it a singleton)
972     * 
973     * The reason for being conservative and throwing an exception is
974     * that when writing 'new(args)' in an object that does not implement
975     * new itself, this will implicitly lead to invoking root.new(args), not
976     * self.new(args), as the user will probably have intended.
977     * To catch such bugs quickly, root.new throws an exception rather than
978     * silently returning the root itself.
979     */
980    public ATObject base_new(ATObject[] initargs) throws InterpreterException {
981    	// root.new(@initargs)
982	    return Evaluator.getGlobalLexicalScope().base_new(initargs);
983    }
984    
985	/**
986	 * After deserialization, ensure that the lexical root remains unique.
987	 */
988	public ATObject meta_resolve() throws InterpreterException {
989		return OBJLexicalRoot._INSTANCE_;
990	}
991    
992}