PageRenderTime 51ms CodeModel.GetById 16ms app.highlight 30ms RepoModel.GetById 1ms app.codeStats 1ms

/interpreter/tags/at2dist090708/src/edu/vub/at/objects/mirrors/NATMirage.java

http://ambienttalk.googlecode.com/
Java | 602 lines | 400 code | 98 blank | 104 comment | 8 complexity | 51ca7db199d8dcec3ea22a2d175ecfe1 MD5 | raw file
  1/**
  2 * AmbientTalk/2 Project
  3 * NATMirage.java created on Oct 2, 2006 at 10:08:12 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.mirrors;
 29
 30import edu.vub.at.actors.ATAsyncMessage;
 31import edu.vub.at.eval.Evaluator;
 32import edu.vub.at.exceptions.InterpreterException;
 33import edu.vub.at.exceptions.XIllegalArgument;
 34import edu.vub.at.exceptions.XTypeMismatch;
 35import edu.vub.at.objects.ATBoolean;
 36import edu.vub.at.objects.ATClosure;
 37import edu.vub.at.objects.ATContext;
 38import edu.vub.at.objects.ATField;
 39import edu.vub.at.objects.ATMethod;
 40import edu.vub.at.objects.ATMethodInvocation;
 41import edu.vub.at.objects.ATNil;
 42import edu.vub.at.objects.ATObject;
 43import edu.vub.at.objects.ATTable;
 44import edu.vub.at.objects.ATTypeTag;
 45import edu.vub.at.objects.coercion.NativeTypeTags;
 46import edu.vub.at.objects.grammar.ATAssignmentSymbol;
 47import edu.vub.at.objects.grammar.ATSymbol;
 48import edu.vub.at.objects.natives.FieldMap;
 49import edu.vub.at.objects.natives.MethodDictionary;
 50import edu.vub.at.objects.natives.NATCallframe;
 51import edu.vub.at.objects.natives.NATMethodInvocation;
 52import edu.vub.at.objects.natives.NATNil;
 53import edu.vub.at.objects.natives.NATObject;
 54import edu.vub.at.objects.natives.NATTable;
 55import edu.vub.at.objects.natives.NATText;
 56import edu.vub.at.objects.natives.grammar.AGSymbol;
 57
 58import java.util.LinkedList;
 59import java.util.Vector;
 60
 61/**
 62 * A NATMirage is an object that forwards all meta-operations invoked upon it (at
 63 * the java-level) to its designated mirror object. To cut off infinite meta-regress
 64 * it also has magic_ variants of them which delegate to the default implementation.
 65 *
 66 * @author smostinc
 67 */
 68public class NATMirage extends NATObject {
 69
 70	// Whenever this field is set, the object should be tested for the _MIRROR_ native type tag
 71	private ATObject mirror_;
 72	
 73	public static NATMirage createMirage(ATClosure code, ATObject dynamicParent, boolean parentType, ATTypeTag[] types, ATObject mirror) throws InterpreterException {
 74		// create a new, uninitialized mirage
 75		NATMirage newMirage = new NATMirage(dynamicParent, code.base_context().base_lexicalScope(), parentType, types);
 76			
 77		ATObject theMirror;
 78		if (mirror.meta_isTaggedAs(NativeTypeTags._CLOSURE_).asNativeBoolean().javaValue) {
 79			// the mirror argument is a constructor closure: the mirror to be used
 80			// is the return value of applying the closure
 81			theMirror = mirror.asClosure().base_apply(NATTable.of(newMirage));
 82		} else {
 83			// create a new instance of the mirror prototype with the uninitialized mirage,
 84			// this implicitly clones the mirror and re-initializes it, setting the base field
 85			// to this new mirage
 86			// def mirrorClone := mirror.new(<uninitialized mirage>)
 87			theMirror = mirror.impl_invoke(mirror, NATNil._NEW_NAME_, NATTable.of(newMirage));	
 88		}
 89
 90		if (theMirror.meta_isTaggedAs(NativeTypeTags._MIRROR_).asNativeBoolean().javaValue) {
 91			// set the mirage's mirror to the cloned mirror
 92			newMirage.initializeWithMirror(theMirror);
 93			return newMirage;
 94		} else {
 95			throw new XIllegalArgument("Object used as a mirror without having the Mirror type tag: " + theMirror);
 96		}
 97	}
 98	
 99	/**
100	 * Dedicated constructor for creating the initial empty mirage tied to the mirror root prototype.
101	 */
102	protected NATMirage(NATMirrorRoot mirror) {
103		super();
104		mirror_ = mirror;
105	}
106	
107	public NATMirage(ATObject dynamicParent, ATObject lexParent, boolean parentType, ATTypeTag[] types) {
108		super(dynamicParent, lexParent, parentType, types);
109		mirror_ = Evaluator.getNil(); // set to nil while not initialized
110	}
111	
112	/**
113	 * Private setter to be used in OBJMirrorRoot.init to break the chicken-and-egg cycle when
114	 * having to create both a mirror and its mirage simultaneously. The sequence is as follows:
115	 *  1) a new empty 'uninitialized' mirage is created, with mirror as nil
116	 *  2) a mirror is instantiated, leading to the invocation of its init method
117	 *  3) the initialization of a new OBJMirrorRoot assigns the uninitialized mirage to its 'base' field
118	 *  4) the mirror field of the uninitialized mirage is set to the newly created mirror, using this method.
119	 */
120	private void initializeWithMirror(ATObject realMirror) {
121		mirror_ = realMirror;
122	}
123	
124	/**
125	 * Constructs a new ambienttalk mirage as a clone of an existing one. This results in a new
126	 * uninitialized mirage (i.e. a mirage whose mirror points to nil). The code that clones the
127	 * mirage must ensure that the mirror is correctly bound to a new instance of the cloned mirage's mirror.
128	
129	 * 
130	 * 
131	 */
132	protected NATMirage(FieldMap map,
133			         Vector state,
134			         LinkedList customFields,
135			         MethodDictionary methodDict,
136			         ATObject dynamicParent,
137			         ATObject lexicalParent,
138			         byte flags,
139			         ATTypeTag[] types) throws InterpreterException {
140		super(map, state, customFields, methodDict, dynamicParent, lexicalParent, flags, types);
141		mirror_ = Evaluator.getNil();
142	}
143	
144    public boolean isMirage() {
145    	return true;
146    }
147	
148	public NATMirage asMirage() throws XTypeMismatch {
149		return this;
150	}
151	
152	// Called by the default NATObject Cloning algorithm
153	protected NATObject createClone(FieldMap map,
154			Vector state,
155			LinkedList customFields,
156			MethodDictionary methodDict,
157			ATObject dynamicParent,
158			ATObject lexicalParent,
159			byte flags, ATTypeTag[] types) throws InterpreterException {
160		NATMirage clonedMirage = new NATMirage(map,
161				state,
162				customFields,
163				methodDict,
164				dynamicParent,
165				lexicalParent,
166				flags,
167				types);
168        // clonedMirage.mirror := myMirror.new(clonedMirage)
169		clonedMirage.mirror_ = mirror_.impl_invoke(mirror_, NATNil._NEW_NAME_, NATTable.of(clonedMirage));
170		return clonedMirage;
171	}
172	
173	/**
174	 * Access to the mirage's mirror, to enable a mirage to be 'upped' to a mirror value.
175	 */
176	protected ATObject getMirror() {
177		return mirror_;
178	}
179	
180	// MAGIC METHODS 
181	// Cut-off for infinite meta-regress
182	
183	public ATNil magic_addMethod(ATMethod method) throws InterpreterException {
184		return super.meta_addMethod(method);
185	}
186
187	public ATObject magic_clone() throws InterpreterException {
188		return super.meta_clone();
189	}
190	
191	public ATNil magic_defineField(ATSymbol name, ATObject value) throws InterpreterException {
192		return super.meta_defineField(name, value);
193	}
194
195	public ATMethod magic_grabMethod(ATSymbol selector) throws InterpreterException {
196		return super.meta_grabMethod(selector);
197	}
198
199	/**
200	 * <tt>invoke</tt> deviates from the default super-calling behaviour because
201	 * the inherited <tt>invoke</tt> implementation from {@link NATCallframe}
202	 * performs a self-send to {@link this#impl_selectAccessor(ATObject, ATSymbol)}
203	 * or {@link this#impl_selectMutator(ATObject, ATAssignmentSymbol)}. However,
204	 * these methods are overridden in the mirage to transform the impl methods into
205	 * <tt>invoke</tt> methods, which causes an infinite loop.
206	 * To break the loop, the inherited implementation is duplicated here, and the
207	 * self-sends are replaced by static super-sends, such that the native implementation
208	 * of the impl methods can be reused.
209	 */
210	public ATObject magic_invoke(ATObject receiver, ATMethodInvocation inv) throws InterpreterException {
211		ATSymbol selector = inv.base_selector();
212		ATTable arguments = inv.base_arguments();
213		//return super.meta_invoke(receiver, selector, arguments);
214		// If the selector is an assignment symbol (i.e. `field:=) try to assign the corresponding field
215		if (selector.isAssignmentSymbol()) {
216			return super.impl_invokeMutator(receiver, selector.asAssignmentSymbol(), arguments);
217		} else {
218			return super.impl_invokeAccessor(receiver, selector, arguments);
219		}
220	}
221
222	public ATTable magic_listMethods() throws InterpreterException {
223		return super.meta_listMethods();
224	}
225
226	public ATObject magic_newInstance(ATTable initargs) throws InterpreterException {
227		return super.meta_newInstance(initargs);
228	}
229
230	public NATText magic_print() throws InterpreterException {
231		return super.meta_print();
232	}
233
234	public ATObject magic_receive(ATAsyncMessage message) throws InterpreterException {
235		return super.meta_receive(message);
236	}
237
238	public ATBoolean magic_respondsTo(ATSymbol selector) throws InterpreterException {
239		return super.meta_respondsTo(selector);
240	}
241
242	/**
243	 * <tt>select</tt> deviates from the default super-calling behaviour because
244	 * the inherited <tt>select</tt> implementation from {@link NATCallframe}
245	 * performs a self-send to {@link this#impl_selectAccessor(ATObject, ATSymbol)}
246	 * or {@link this#impl_selectMutator(ATObject, ATAssignmentSymbol)}. However,
247	 * these methods are overridden in the mirage to transform the impl methods into
248	 * <tt>select</tt> methods, which causes an infinite loop.
249	 * To break the loop, the inherited implementation is duplicated here, and the
250	 * self-sends are replaced by static super-sends, such that the native implementation
251	 * of the impl methods can be reused.
252	 */
253	public ATClosure magic_select(ATObject receiver, ATSymbol selector) throws InterpreterException {
254		//return super.meta_select(receiver, selector);
255		if (selector.isAssignmentSymbol()) {
256			return super.impl_selectMutator(receiver, selector.asAssignmentSymbol());
257		} else {
258			return super.impl_selectAccessor(receiver, selector);
259		}
260	}
261
262	
263	public ATClosure magic_doesNotUnderstand(ATSymbol selector) throws InterpreterException {
264		return super.meta_doesNotUnderstand(selector);
265	}
266	
267	
268	public ATNil magic_addField(ATField field) throws InterpreterException {
269		return super.meta_addField(field);
270	}
271
272	
273	public ATField magic_grabField(ATSymbol selector) throws InterpreterException {
274		return super.meta_grabField(selector);
275	}
276
277	
278	public ATTable magic_listFields() throws InterpreterException {
279		return super.meta_listFields();
280	}
281	
282	public ATNil magic_addSlot(ATMethod slot) throws InterpreterException {
283		return super.meta_addSlot(slot);
284	}
285
286	
287	public ATMethod magic_grabSlot(ATSymbol selector) throws InterpreterException {
288		return super.meta_grabSlot(selector);
289	}
290
291	
292	public ATTable magic_listSlots() throws InterpreterException {
293		return super.meta_listSlots();
294	}
295
296
297	public ATObject magic_send(ATObject receiver, ATAsyncMessage message) throws InterpreterException {
298		return super.meta_send(receiver, message);
299	}
300
301
302	public ATObject magic_eval(ATContext ctx) throws InterpreterException {
303		return super.meta_eval(ctx);
304	}
305
306
307	public ATObject magic_quote(ATContext ctx) throws InterpreterException {
308		return super.meta_quote(ctx);
309	}
310	
311	public ATBoolean magic_isExtensionOfParent() throws InterpreterException {
312		return super.meta_isExtensionOfParent();
313	}
314
315	public ATObject magic_invokeField(ATObject rcv, ATSymbol sym) throws InterpreterException {
316		return super.meta_invokeField(rcv, sym);
317	}
318	
319	public ATObject magic_pass() throws InterpreterException {
320		return super.meta_pass();
321	}
322	
323	public ATObject magic_resolve() throws InterpreterException {
324		return super.meta_resolve();
325	}
326	
327	public ATBoolean magic_isTaggedAs(ATTypeTag type) throws InterpreterException {
328		return super.meta_isTaggedAs(type);
329	}
330	
331	public ATTable magic_typeTags() throws InterpreterException {
332		return super.meta_typeTags();
333	}
334
335	public ATBoolean magic_isCloneOf(ATObject original) throws InterpreterException {
336		return super.meta_isCloneOf(original);
337	}
338
339	public ATBoolean magic_isRelatedTo(ATObject object) throws InterpreterException {
340		return super.meta_isRelatedTo(object);
341	}
342	
343	/* ========================================================================
344	 * Each meta_x method defined in ATObject is implemented in a mirage as a
345	 * forwarding method that asks its mirror to perform the operation on itself
346	 * instead.
347	 * ======================================================================== */
348
349	public ATNil meta_addMethod(ATMethod method) throws InterpreterException {
350		mirror_.impl_invoke(
351				mirror_,
352				AGSymbol.jAlloc("addMethod"),
353				NATTable.atValue(new ATObject[] { method })
354				);
355			
356		return Evaluator.getNil();
357	}
358
359	public ATObject meta_clone() throws InterpreterException {
360		return mirror_.impl_invoke(
361				mirror_,
362				AGSymbol.jAlloc("clone"),
363				NATTable.EMPTY);
364	}
365
366	public ATNil meta_defineField(ATSymbol name, ATObject value) throws InterpreterException {
367		mirror_.impl_invoke(
368				mirror_,
369				AGSymbol.jAlloc("defineField"),
370				NATTable.atValue(new ATObject[] { name, value }));
371		return Evaluator.getNil();
372	}
373	
374	public ATMethod meta_grabMethod(ATSymbol selector) throws InterpreterException {
375		return mirror_.impl_invoke(
376				mirror_,
377				AGSymbol.jAlloc("grabMethod"),
378				NATTable.atValue(new ATObject[] { selector })
379				).asMethod();
380	}
381
382	public ATObject meta_invoke(ATObject delegate, ATMethodInvocation inv) throws InterpreterException {
383		return mirror_.impl_invoke(
384				mirror_,
385				AGSymbol.jAlloc("invoke"),
386				NATTable.atValue(new ATObject[] { delegate, inv }));
387	}
388
389	public ATTable meta_listMethods() throws InterpreterException {
390		return mirror_.impl_invoke(
391				mirror_,
392				AGSymbol.jAlloc("listMethods"),
393				NATTable.EMPTY
394				).asTable();
395	}
396
397	public ATObject meta_newInstance(ATTable initargs) throws InterpreterException {
398		return mirror_.impl_invoke(
399				mirror_,
400				AGSymbol.jAlloc("newInstance"),
401				NATTable.atValue(new ATObject[] { initargs }));
402	}
403
404	public NATText meta_print() throws InterpreterException {
405		return mirror_.impl_invoke(
406					mirror_,
407					AGSymbol.jAlloc("print"),
408					NATTable.EMPTY).asNativeText();
409	}
410
411	public ATObject meta_receive(ATAsyncMessage message) throws InterpreterException {
412		return mirror_.impl_invoke(
413				mirror_,
414				AGSymbol.jAlloc("receive"),
415				NATTable.atValue(new ATObject[] { message }));
416	}
417	
418	public ATBoolean meta_respondsTo(ATSymbol selector) throws InterpreterException {
419		return mirror_.impl_invoke(
420				mirror_,
421				AGSymbol.jAlloc("respondsTo"),
422				NATTable.atValue(new ATObject[] { selector })
423				).asBoolean();
424	}
425
426	public ATClosure meta_select(ATObject receiver, ATSymbol selector) throws InterpreterException {
427		return mirror_.impl_invoke(
428				mirror_,
429				AGSymbol.jAlloc("select"),
430				NATTable.atValue(new ATObject[] { receiver, selector })).asClosure();
431	}
432
433	public ATNil meta_addField(ATField field) throws InterpreterException {
434		mirror_.impl_invoke(
435				mirror_,
436				AGSymbol.jAlloc("addField"),
437				NATTable.atValue(new ATObject[] { field }));
438		return Evaluator.getNil();
439	}
440
441	public ATField meta_grabField(ATSymbol selector) throws InterpreterException {
442		return mirror_.impl_invoke(
443				mirror_,
444				AGSymbol.jAlloc("grabField"),
445				NATTable.atValue(new ATObject[] { selector })).asField();
446	}
447
448
449	public ATTable meta_listFields() throws InterpreterException {
450		return mirror_.impl_invoke(
451				mirror_,
452				AGSymbol.jAlloc("listFields"),
453				NATTable.EMPTY).asTable();
454	}
455	
456	public ATNil meta_addSlot(ATMethod slot) throws InterpreterException {
457		mirror_.impl_invoke(
458				mirror_,
459				AGSymbol.jAlloc("addSlot"),
460				NATTable.atValue(new ATObject[] { slot }));
461		return Evaluator.getNil();
462	}
463
464	public ATMethod meta_grabSlot(ATSymbol selector) throws InterpreterException {
465		return mirror_.impl_invoke(
466				mirror_,
467				AGSymbol.jAlloc("grabSlot"),
468				NATTable.atValue(new ATObject[] { selector })).asMethod();
469	}
470
471
472	public ATTable meta_listSlots() throws InterpreterException {
473		return mirror_.impl_invoke(
474				mirror_,
475				AGSymbol.jAlloc("listSlots"),
476				NATTable.EMPTY).asTable();
477	}
478
479	public ATClosure meta_doesNotUnderstand(ATSymbol selector) throws InterpreterException {
480		return mirror_.impl_invoke(
481				mirror_,
482				AGSymbol.jAlloc("doesNotUnderstand"),
483				NATTable.atValue(new ATObject[] { selector })).asClosure();
484	}
485
486
487	public ATObject meta_send(ATObject receiver, ATAsyncMessage message) throws InterpreterException {
488		return mirror_.impl_invoke(
489				mirror_,
490				AGSymbol.jAlloc("send"),
491				NATTable.atValue(new ATObject[] { receiver, message }));
492	}
493
494
495	public ATObject meta_eval(ATContext ctx) throws InterpreterException {
496		return mirror_.impl_invoke(
497				mirror_,
498				AGSymbol.jAlloc("eval"),
499				NATTable.atValue(new ATObject[] { ctx }));
500	}
501
502
503	public ATObject meta_quote(ATContext ctx) throws InterpreterException {
504		return mirror_.impl_invoke(
505				mirror_,
506				AGSymbol.jAlloc("quote"),
507				NATTable.atValue(new ATObject[] { ctx }));
508	}
509
510	public ATBoolean meta_isExtensionOfParent() throws InterpreterException {
511		return mirror_.impl_invoke(
512				mirror_,
513				AGSymbol.jAlloc("isExtensionOfParent"),
514				NATTable.EMPTY).asBoolean();
515	}
516
517	public ATObject meta_invokeField(ATObject rcv, ATSymbol sym) throws InterpreterException {
518		return mirror_.impl_invoke(
519				mirror_,
520				AGSymbol.jAlloc("invokeField"),
521				NATTable.atValue(new ATObject[] { rcv, sym }));
522	}
523	
524    public ATObject meta_pass() throws InterpreterException {
525    	return mirror_.impl_invoke(
526				mirror_, AGSymbol.jAlloc("pass"), NATTable.EMPTY);
527    }
528    
529    public ATObject meta_resolve() throws InterpreterException {
530    	return mirror_.impl_invoke(
531				mirror_, AGSymbol.jAlloc("resolve"), NATTable.EMPTY);
532    }
533    
534    public ATBoolean meta_isTaggedAs(ATTypeTag type) throws InterpreterException {
535    	return mirror_.impl_invoke(
536				mirror_, AGSymbol.jAlloc("isTaggedAs"), NATTable.of(type)).asBoolean();
537    }
538    
539    public ATTable meta_typeTags() throws InterpreterException {
540		return mirror_.impl_invoke(
541				mirror_,
542				AGSymbol.jAlloc("typeTags"),
543				NATTable.EMPTY).asTable();
544    }
545	
546	public ATBoolean meta_isCloneOf(ATObject original) throws InterpreterException {
547		return mirror_.impl_invoke(
548				mirror_,
549				AGSymbol.jAlloc("isCloneOf"),
550				NATTable.atValue(new ATObject[] { original })).asBoolean();
551	}
552
553	public ATBoolean meta_isRelatedTo(ATObject object) throws InterpreterException {
554		return mirror_.impl_invoke(
555				mirror_,
556				AGSymbol.jAlloc("isRelatedTo"),
557				NATTable.atValue(new ATObject[] { object })).asBoolean();
558	}
559
560	/** implementation-level method is mapped onto regular MOP method */
561	public ATObject impl_invoke(ATObject receiver, ATSymbol selector, ATTable arguments) throws InterpreterException {
562		return mirror_.impl_invoke(
563				mirror_,
564				AGSymbol.jAlloc("invoke"),
565				NATTable.atValue(new ATObject[] { receiver, new NATMethodInvocation(selector, arguments, NATTable.EMPTY) }));
566	}
567	
568	/** implementation-level method is mapped onto regular MOP method */
569	public ATObject impl_invokeAccessor(ATObject receiver, ATSymbol selector, ATTable arguments) throws InterpreterException {
570		return mirror_.impl_invoke(
571				mirror_,
572				AGSymbol.jAlloc("invoke"),
573				NATTable.atValue(new ATObject[] { receiver, new NATMethodInvocation(selector, arguments, NATTable.EMPTY) }));
574	}
575
576	/** implementation-level method is mapped onto regular MOP method */
577	public ATObject impl_invokeMutator(ATObject receiver, ATAssignmentSymbol selector, ATTable arguments) throws InterpreterException {
578		return mirror_.impl_invoke(
579				mirror_,
580				AGSymbol.jAlloc("invoke"),
581				NATTable.atValue(new ATObject[] { receiver, new NATMethodInvocation(selector, arguments, NATTable.EMPTY) }));
582	}
583
584	/** implementation-level method is mapped onto regular MOP method */
585	public ATClosure impl_selectAccessor(ATObject receiver, ATSymbol selector) throws InterpreterException {
586		return mirror_.impl_invoke(
587				mirror_,
588				AGSymbol.jAlloc("select"),
589				NATTable.atValue(new ATObject[] { receiver, selector })).asClosure();
590	}
591
592	/** implementation-level method is mapped onto regular MOP method */
593	public ATClosure impl_selectMutator(ATObject receiver, ATAssignmentSymbol selector) throws InterpreterException {
594		return mirror_.impl_invoke(
595				mirror_,
596				AGSymbol.jAlloc("select"),
597				NATTable.atValue(new ATObject[] { receiver, selector })).asClosure();
598	}
599	
600	
601	
602}