PageRenderTime 45ms CodeModel.GetById 10ms app.highlight 26ms RepoModel.GetById 2ms app.codeStats 0ms

/interpreter/tags/at_build150307/src/edu/vub/at/objects/natives/OBJLexicalRoot.java

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