PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/interpreter/tags/reactive-pattern-matching/src/edu/vub/at/objects/natives/OBJLexicalRoot.java

http://ambienttalk.googlecode.com/
Java | 1754 lines | 455 code | 121 blank | 1178 comment | 14 complexity | 1b3c4db9dbebe22b27f1274f6a7e273d MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, LGPL-2.1
  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. */
  28. package edu.vub.at.objects.natives;
  29. import edu.vub.at.actors.ATActorMirror;
  30. import edu.vub.at.actors.ATFarReference;
  31. import edu.vub.at.actors.natives.ELActor;
  32. import edu.vub.at.actors.natives.ELVirtualMachine;
  33. import edu.vub.at.actors.natives.NATFarReference;
  34. import edu.vub.at.actors.natives.Packet;
  35. import edu.vub.at.actors.net.OBJNetwork;
  36. import edu.vub.at.eval.Evaluator;
  37. import edu.vub.at.exceptions.InterpreterException;
  38. import edu.vub.at.exceptions.XSelectorNotFound;
  39. import edu.vub.at.exceptions.XUnassignableField;
  40. import edu.vub.at.exceptions.XUndefinedSlot;
  41. import edu.vub.at.objects.ATAbstractGrammar;
  42. import edu.vub.at.objects.ATBoolean;
  43. import edu.vub.at.objects.ATClosure;
  44. import edu.vub.at.objects.ATHandler;
  45. import edu.vub.at.objects.ATMethod;
  46. import edu.vub.at.objects.ATNil;
  47. import edu.vub.at.objects.ATNumber;
  48. import edu.vub.at.objects.ATNumeric;
  49. import edu.vub.at.objects.ATObject;
  50. import edu.vub.at.objects.ATTable;
  51. import edu.vub.at.objects.ATText;
  52. import edu.vub.at.objects.ATTypeTag;
  53. import edu.vub.at.objects.coercion.NativeTypeTags;
  54. import edu.vub.at.objects.grammar.ATAssignmentSymbol;
  55. import edu.vub.at.objects.grammar.ATSymbol;
  56. import edu.vub.at.objects.mirrors.NATMirage;
  57. import edu.vub.at.objects.mirrors.NATMirrorRoot;
  58. import edu.vub.at.objects.natives.grammar.AGSymbol;
  59. import edu.vub.at.parser.NATParser;
  60. import edu.vub.at.signals.ATBehavior;
  61. import edu.vub.at.signals.ATEventSource;
  62. import edu.vub.at.signals.natives.NATBehavior;
  63. import edu.vub.at.signals.natives.NATEventSource;
  64. /**
  65. * The singleton instance of this class represents the lexical root of an actor.
  66. * Since this lexical root is constant (it cannot be modified) and contains no mutable fields,
  67. * it is possible to share a singleton instance of this class among all actors.
  68. * <p>
  69. * The lexical root is an object containing globally visible AmbientTalk native methods.
  70. * Such methods include control structures such as <tt>if:then:else:</tt>
  71. * but also object creation methods like <tt>object:</tt> and reflective constructs
  72. * like <tt>reflect:</tt>.
  73. *
  74. * Furthermore, the lexical root is also the root of the lexical parent hierarchy for objects.
  75. * This means that this object's mirror is responsible for ending recursive meta-level methods
  76. * such as <tt>lookup</tt> and <tt>assignField</tt>.
  77. * <p>
  78. * Like any class whose instances represent native AmbientTalk objects, this class is a subclass
  79. * of {@link NativeATObject}. This means that this class can use the typical protocol of native objects
  80. * to implement base-level AmbientTalk methods as Java methods whose name is prefixed with
  81. * <tt>base_</tt>.
  82. * <p>
  83. * Note that OBJLexicalRoot is a <i>sentinel</i> class. The actual object bound to the
  84. * lexical root of an actor (accessible via the field <tt>root</tt> will be a normal
  85. * AmbientTalk object whose lexical parent is this object.
  86. * The real, empty, root object is local to each actor and is mutable. The definitions
  87. * from the <tt>init.at</tt> file are added to that object.
  88. *
  89. * @author smostinc
  90. * @author tvcutsem
  91. */
  92. public final class OBJLexicalRoot extends NATByCopy {
  93. /**
  94. * The singleton instance of the sentinel lexical root
  95. */
  96. static public final OBJLexicalRoot _INSTANCE_ = new OBJLexicalRoot();
  97. /**
  98. * Constructor made private for singleton design pattern
  99. */
  100. private OBJLexicalRoot() { }
  101. /**
  102. * The lexical root has a special lexical parent object which ends the recursion
  103. * along the lexical lookup chain. These methods cannot be implemented
  104. * directly in this class because this class still implements useful
  105. * <tt>base_</tt> Java methods which have to be invoked by means of the
  106. * implementations defined in {@link NativeATObject}.
  107. */
  108. private final NativeATObject lexicalSentinel_ = new NATByCopy() {
  109. // METHODS THAT END THE LEXICAL LOOKUP CHAIN
  110. public ATObject impl_callAccessor(ATSymbol selector, ATTable arguments) throws InterpreterException {
  111. throw new XUndefinedSlot("variable access", selector.toString());
  112. }
  113. public ATObject impl_callMutator(ATAssignmentSymbol selector, ATTable arguments) throws InterpreterException {
  114. throw new XUnassignableField(selector.toString());
  115. }
  116. public ATObject impl_callField(ATSymbol selector) throws InterpreterException {
  117. throw new XUndefinedSlot("variable access", selector.toString());
  118. }
  119. public ATClosure impl_lookupAccessor(final ATSymbol selector) throws InterpreterException {
  120. throw new XUndefinedSlot("accessor", selector.toString());
  121. }
  122. public ATClosure impl_lookupMutator(ATAssignmentSymbol selector) throws InterpreterException {
  123. throw new XUnassignableField(selector.toString());
  124. }
  125. public NATText meta_print() throws InterpreterException {
  126. return NATText.atValue("lexicalrootsentinel");
  127. }
  128. };
  129. public ATObject impl_lexicalParent() {
  130. return lexicalSentinel_;
  131. }
  132. /* -----------------------
  133. * -- Primitive Methods --
  134. * ----------------------- */
  135. /* ===============================================================================
  136. * NOTE: the code below has been replaced by dedicated syntax and AST elements.
  137. * However, the skeleton of this code may still prove useful in the future, if
  138. * we ever plan to implement all base_ native methods as true AmbientTalk methods
  139. * (i.e. as PrimitiveMethod instances).
  140. * ===============================================================================
  141. */
  142. /*
  143. private static final AGSymbol _IMPORT_NAME_ = AGSymbol.jAlloc("import:");
  144. private static final AGSymbol _IMPORT_ALIAS_NAME_ = AGSymbol.jAlloc("import:alias:");
  145. private static final AGSymbol _IMPORT_EXCLUDE_NAME_ = AGSymbol.jAlloc("import:exclude:");
  146. private static final AGSymbol _IMPORT_ALIAS_EXCLUDE_NAME_ = AGSymbol.jAlloc("import:alias:exclude:");
  147. private static final AGSymbol _SRC_PARAM_ = AGSymbol.jAlloc("sourceObject");
  148. private static final AGSymbol _ALIAS_PARAM_ = AGSymbol.jAlloc("aliases");
  149. private static final AGSymbol _EXCLUDE_PARAM_ = AGSymbol.jAlloc("exclude");
  150. */
  151. /*protected static final PrimitiveMethod _PRIM_IMPORT_ = new PrimitiveMethod(_IMPORT_NAME_, NATTable.atValue(new ATObject[] { _SRC_PARAM_ })) {
  152. public ATObject base_apply(ATTable arguments, ATContext ctx) throws InterpreterException {
  153. ATObject sourceObject = arguments.base_at(NATNumber.ONE);
  154. return performImport(sourceObject, ctx, new Hashtable(), OBJLexicalRoot.getDefaultExcludedSlots());
  155. }
  156. };*/
  157. /**
  158. * def import: sourceObject alias: [ `oldname -> `newname , ... ]
  159. */
  160. /*protected static final PrimitiveMethod _PRIM_IMPORT_ALIAS_ = new PrimitiveMethod(_IMPORT_ALIAS_NAME_, NATTable.atValue(new ATObject[] { _SRC_PARAM_, _ALIAS_PARAM_ })) {
  161. public ATObject base_apply(ATTable arguments, ATContext ctx) throws InterpreterException {
  162. ATObject sourceObject = arguments.base_at(NATNumber.ONE);
  163. ATObject aliases = arguments.base_at(NATNumber.atValue(2));
  164. return performImport(sourceObject, ctx, preprocessAliases(aliases.base_asTable()), OBJLexicalRoot.getDefaultExcludedSlots());
  165. }
  166. };*/
  167. /**
  168. * def import: sourceObject excludes: [ `name1, `name2, ... ]
  169. */
  170. /*protected static final PrimitiveMethod _PRIM_IMPORT_EXCLUDE_ = new PrimitiveMethod(_IMPORT_EXCLUDE_NAME_, NATTable.atValue(new ATObject[] { _SRC_PARAM_, _EXCLUDE_PARAM_ })) {
  171. public ATObject base_apply(ATTable arguments, ATContext ctx) throws InterpreterException {
  172. ATObject sourceObject = arguments.base_at(NATNumber.ONE);
  173. ATObject exclusions = arguments.base_at(NATNumber.atValue(2));
  174. return performImport(sourceObject, ctx, new Hashtable(), preprocessExcludes(exclusions.base_asTable()));
  175. }
  176. };*/
  177. /**
  178. * def import: sourceObject alias: [ `oldname -> `newname, ... ] excludes: [ `name1, `name2, ... ]
  179. */
  180. /*protected static final PrimitiveMethod _PRIM_IMPORT_ALIAS_EXCLUDE_ = new PrimitiveMethod(_IMPORT_ALIAS_EXCLUDE_NAME_,
  181. NATTable.atValue(new ATObject[] { _SRC_PARAM_, _ALIAS_PARAM_, _EXCLUDE_PARAM_ })) {
  182. public ATObject base_apply(ATTable arguments, ATContext ctx) throws InterpreterException {
  183. ATObject sourceObject = arguments.base_at(NATNumber.ONE);
  184. ATObject aliases = arguments.base_at(NATNumber.atValue(2));
  185. ATObject exclusions = arguments.base_at(NATNumber.atValue(3));
  186. return performImport(sourceObject, ctx, preprocessAliases(aliases.base_asTable()), preprocessExcludes(exclusions.base_asTable()));
  187. }
  188. };*/
  189. /**
  190. * Invoked whenever a new true AmbientTalk object is created that should
  191. * represent the root. This gives the lexical root a chance to install its
  192. * primitive methods.
  193. */
  194. /*public static void initializeRoot(NATObject root) {
  195. try {
  196. // add import: native
  197. root.meta_addMethod(_PRIM_IMPORT_);
  198. // add import:alias: native
  199. root.meta_addMethod(_PRIM_IMPORT_ALIAS_);
  200. // add import:exclude: native
  201. root.meta_addMethod(_PRIM_IMPORT_EXCLUDE_);
  202. // add import:alias:exclude: native
  203. root.meta_addMethod(_PRIM_IMPORT_ALIAS_EXCLUDE_);
  204. } catch (InterpreterException e) {
  205. Logging.Init_LOG.fatal("Failed to initialize the root!", e);
  206. }
  207. }*/
  208. /* ----------------------
  209. * -- Global variables --
  210. * ---------------------- */
  211. /**
  212. * <tt>nil</tt> evaluates to the nil object, which is
  213. * the empty, dynamic parent of all AmbientTalk objects.
  214. */
  215. public ATNil base_nil() {
  216. return Evaluator.getNil();
  217. }
  218. /**
  219. * <tt>true</tt> evaluates to the unique boolean true object.
  220. */
  221. public ATBoolean base_true() {
  222. return NATBoolean._TRUE_;
  223. }
  224. /**
  225. * <tt>false</tt> evaluates to the unique boolean false object.
  226. */
  227. public ATBoolean base_false() {
  228. return NATBoolean._FALSE_;
  229. }
  230. /**
  231. * <tt>/</tt> evaluates to the global namespace. It is
  232. * simply an alias for <tt>lobby</tt>.
  233. * @see #base_lobby()
  234. */
  235. public ATObject base__opdiv_() {
  236. return base_lobby();
  237. }
  238. /**
  239. * <tt>lobby</tt> evaluates to the global namespace object.
  240. * For each <tt>name=path</tt> entry on AmbientTalk's
  241. * <i>object path</i>, the lobby object contains a slot
  242. * <tt>name</tt> bound to a namespace object bound to
  243. * the directory referred to by <tt>path</tt>.
  244. * <p>
  245. * Accessing the lobby allows loading in AmbientTalk source code
  246. * from external files.
  247. */
  248. public ATObject base_lobby() {
  249. return Evaluator.getLobbyNamespace();
  250. }
  251. /**
  252. * <tt>root</tt> evaluates to the global lexical scope object.
  253. * This is the top-level object in which the definitions of
  254. * the file <tt>at/init/init.at</tt> are evaluated. All code
  255. * is assumed to be "nested" in the lexical root, so all definitions
  256. * of this object are lexically accessible.
  257. */
  258. public ATObject base_root() {
  259. return Evaluator.getGlobalLexicalScope();
  260. }
  261. /**
  262. * <tt>jlobby</tt> evaluates to the Java namespace root. It is a
  263. * special object which is part of the symbiosis infrastructure of
  264. * AmbientTalk. <tt>jlobby</tt> acts like an object that has field
  265. * names that correspond to Java package names. By selecting fields
  266. * from this object, an appropriate Java package can be created
  267. * from which a Java class can be accessed. Only the Java classes
  268. * accessible in the Java classpath are accessible.
  269. *
  270. * Example:
  271. * <code>jlobby.java.util.Vector</code> evaluates to a reference to
  272. * the Java <tt>Vector</tt> class.
  273. */
  274. public ATObject base_jlobby() {
  275. return Evaluator.getJLobbyRoot();
  276. }
  277. /**
  278. * <tt>network</tt> evaluates to the unique network control object.
  279. * It is a simple native object with two methods:
  280. * <ul>
  281. * <li><tt>network.online()</tt> makes the interpreter go online. This allows
  282. * publications of local actors to be discovered by remote objects and vice versa.
  283. * <li><tt>network.offline()</tt> makes the interpreter go offline. All
  284. * remote references to remote objects will become disconnected.
  285. * </ul>
  286. */
  287. public ATObject base_network() {
  288. return OBJNetwork._INSTANCE_;
  289. }
  290. /**
  291. * <tt>defaultMirror</tt> evaluates to the default mirror on objects. This
  292. * is the mirror encapsulating the standard AmbientTalk object semantics.
  293. * That is, it is a mirror with similar behaviour as the mirror created by
  294. * executing: <code>reflect: (object: { ... })</code>.
  295. *
  296. * The default mirror is an object with a read-only <tt>base</tt> field
  297. * that signifies the base-level object of this mirror. The main purpose
  298. * of this object is to serve as a prototype whose methods can be overridden
  299. * by custom mirrors. The syntax:
  300. * <pre>
  301. * mirror: { ... }
  302. * </pre>
  303. * is syntactic sugar for:
  304. * <pre>
  305. * extend: defaultMirror with: { ... }
  306. * </pre>
  307. *
  308. * Note that the default mirror is typed with the <tt>/.at.types.Mirror</tt> type.
  309. */
  310. public ATObject base_defaultMirror() {
  311. return Evaluator.getMirrorRoot();
  312. }
  313. /* ------------------------
  314. * -- Control Structures --
  315. * ------------------------ */
  316. /**
  317. * The <tt>if:then:</tt> control structure. Usage:
  318. * <pre>if: cond then: consequent</pre>
  319. *
  320. * pseudo-implementation:
  321. * <pre>cond.ifTrue: consequent</pre>
  322. *
  323. * Note that the consequent parameter should be a <i>closure</i>, i.e.
  324. * the caller is responsible for delaying the evaluation of the consequent!
  325. *
  326. * @param cond a boolean object
  327. * @param consequent a closure containing the code to execute if the boolean is true
  328. * @return if <tt>cond</tt> is true, the value of applying the consequent, <tt>nil</tt> otherwise
  329. */
  330. public ATObject base_if_then_(ATBoolean cond, ATClosure consequent) throws InterpreterException {
  331. return cond.base_ifTrue_(consequent);
  332. }
  333. /**
  334. * The <tt>if:then:else:</tt> control structure. Usage:
  335. * <pre>if: cond then: consequent else: alternative</pre>
  336. *
  337. * pseudo-implementation:
  338. * <pre>cond.ifTrue: consequent ifFalse: alternative</pre>
  339. *
  340. * Note that the consequent and alternative parameters should be <i>closures</i>, i.e.
  341. * the caller is responsible for delaying the evaluation of these arguments!
  342. *
  343. * @param cond a boolean object
  344. * @param consequent a closure containing the code to execute if the boolean is true
  345. * @param alternative a closure containing the code to execute if the boolean is false
  346. * @return the value of consequent if the boolean is true, the value of the alternative otherwise.
  347. */
  348. public ATObject base_if_then_else_(ATBoolean cond, ATClosure consequent, ATClosure alternative) throws InterpreterException {
  349. return cond.base_ifTrue_ifFalse_(consequent, alternative);
  350. }
  351. /**
  352. * The <tt>while:do:</tt> control structure. Usage:
  353. * <pre>while: condition do: body</pre>
  354. *
  355. * pseudo-implementation:
  356. * <pre>condition.whileTrue: body</pre>
  357. *
  358. * Note that <i>both</i> the condition and the body should be <i>closures</i>, because
  359. * they represent pieces of code that have to be executed repeatedly. Because of traditional
  360. * syntax, novice programmers are inclined to make the mistake of writing, e.g.:
  361. * <pre>while: (i < 10) do: { i := i + 1 }</pre>
  362. * Which is wrong because the first parameter should evaluate to a closure that itself
  363. * returns a boolean value, not to a boolean value directly.
  364. *
  365. * @param condition a closure expected to return a boolean object
  366. * @param body a closure containing the code to execute as long as the condition closure returns true
  367. * @return if conditions is true at least once, the last value of body, <tt>nil</tt> otherwise.
  368. */
  369. public ATObject base_while_do_(ATClosure condition, ATClosure body) throws InterpreterException {
  370. return condition.base_whileTrue_(body);
  371. }
  372. /**
  373. * The <tt>foreach:in:</tt> control structure. Usage:
  374. *
  375. * <pre>foreach: body in: table</pre>
  376. *
  377. * pseudo-implementation:
  378. * <pre>table.each: body</pre>
  379. *
  380. * Example: <code>[1,2,3].each: { |i| system.println(i) }</code>
  381. *
  382. * @param body a one-arity closure that is to be applied to each element of the table
  383. * @param tab a table to apply the body closure to
  384. * @return <tt>nil</tt>, by default
  385. */
  386. public ATObject base_foreach_in_(ATClosure body, ATTable tab) throws InterpreterException {
  387. return tab.base_each_(body);
  388. }
  389. /**
  390. * The <tt>do:if:</tt> control structure. Usage:
  391. * <pre>do: body if: condition</pre>
  392. *
  393. * pseudo-implementation:
  394. * <pre>condition.ifTrue: body</pre>
  395. *
  396. * In Ruby, this kind of control structure is called a <i>statement modifier</i>.
  397. *
  398. * @param body a zero-argument closure to execute if the condition is true
  399. * @param condition a boolean value
  400. * @return the result of invoking body if the condition is true or nil if the
  401. * condition is false
  402. */
  403. public ATObject base_do_if_(ATClosure body, ATBoolean condition) throws InterpreterException {
  404. return condition.base_ifTrue_(body);
  405. }
  406. /**
  407. * The <tt>do:unless:</tt> control structure. Usage:
  408. * <pre>do: body unless: condition</pre>
  409. *
  410. * pseudo-implementation:
  411. * <pre>condition.ifFalse: body</pre>
  412. *
  413. * In Ruby, this kind of control structure is called a <i>statement modifier</i>.
  414. * Example: <code>do: { file.close() } unless: (nil == file)</code>
  415. *
  416. * @param body a zero-argument closure to execute only if the condition is false
  417. * @param condition a boolean value
  418. * @return the result of invoking body if the condition is false, nil otherwise
  419. */
  420. public ATObject base_do_unless_(ATClosure body, ATBoolean condition) throws InterpreterException {
  421. return condition.base_ifFalse_(body);
  422. }
  423. /**
  424. * The <tt>let:</tt> construct. Usage:
  425. * <pre>let: { |var := value| body }</pre>
  426. *
  427. * pseudo-implementation:
  428. * <pre>closure()</pre>
  429. *
  430. * <tt>let:</tt> allows for the easy creation of temporary local variables.
  431. * This construct should be used in conjunction with a closure that declares optional
  432. * parameters. Because the closure will be invoked with zero arguments, all of the
  433. * parameters will be given their corresponding default initial value. The parameters
  434. * are defined local to the closure's body.
  435. *
  436. * AmbientTalk's <tt>let:</tt> behaves like Scheme's <tt>let*</tt> and <tt>letrec</tt>,
  437. * i.e. the following is legal:
  438. * <pre>let: {
  439. * |var1 := value1,
  440. * var2 := var1,
  441. * var3 := { ... var3() ... }|
  442. * ...
  443. *}</pre>
  444. *
  445. * @param body a closure which is supposed to declare some optional parameters
  446. * @return the result of invoking the body closure
  447. */
  448. public ATObject base_let_(ATClosure body) throws InterpreterException {
  449. return body.base_apply(NATTable.EMPTY);
  450. }
  451. /* ------------------------------------------
  452. * -- Actor Creation and accessing Methods --
  453. * ------------------------------------------ */
  454. /**
  455. * The <tt>actor: closure</tt> construct.
  456. *
  457. * The semantics of actor creation is as follows:
  458. * <ul>
  459. * <li> Mandatory parameters to the block of initialization code are treated as lexically visible
  460. * variables that have to remain available in the new actor behaviour. Hence, these variables
  461. * are evaluated to values immediately at creation-time and parameter-passed to the new actor.
  462. * <li> The closure containing the initialization code is unpacked, its lexical scope is disregarded
  463. * and the unwrapped method is serialized and sent to the new actor, which can use it to
  464. * initialize his behaviour object.
  465. * <li>The creating actor waits for the created actor to spawn a new behaviour and to return a far
  466. * reference to this behaviour. From that point on, the creating actor can run in parallel with
  467. * the created actor, which only then evaluates the initialization code to initialize its behaviour.
  468. * </ul>
  469. *
  470. * @param closure the closure whose parameters define lexical fields to be copied and whose
  471. * method specifies the code of the new actor's behaviour object
  472. * @return a far reference to the behaviour of the new actor
  473. */
  474. public ATObject base_actor_(ATClosure closure) throws InterpreterException {
  475. ATMethod method = closure.base_method();
  476. NATTable copiedBindings = Evaluator.evalMandatoryPars(
  477. method.base_parameters(),
  478. closure.base_context());
  479. Packet serializedBindings = new Packet("actor-bindings", copiedBindings);
  480. Packet serializedInitCode = new Packet("actor-initcode", method);
  481. return ELVirtualMachine.currentVM().createActor(serializedBindings, serializedInitCode);
  482. }
  483. /**
  484. * <tt>reflectOnActor</tt> evaluates to the mirror on the actor executing this code.
  485. * The actor mirror is an object whose behaviour is consulted for operations
  486. * such as creating and sending asynchronous messages or creating mirrors on
  487. * other objects. It can be replaced by a custom mirror by means of the actor
  488. * mirror's <tt>getExplicitActorMirror</tt> method.
  489. */
  490. public ATActorMirror base_reflectOnActor() throws InterpreterException {
  491. return ELActor.currentActor().getImplicitActorMirror().base_getExplicitActorMirror();
  492. }
  493. /**
  494. * The <tt>export: object as: topic</tt> construct. Pseudo-implementation:
  495. * <pre>actor.provide(topic, object)</pre>
  496. *
  497. * This construct enables the given object to become discoverable by objects
  498. * in other actors by means of the topic type.
  499. *
  500. * @param object the object to export to remote actors' objects
  501. * @param topic a type denoting the abstract 'publication topic' for this object's publication
  502. * @return a publication object whose <tt>cancel</tt> method can be used to cancel the publication.
  503. */
  504. public ATObject base_export_as_(ATObject object, ATTypeTag topic) throws InterpreterException {
  505. return ELActor.currentActor().getImplicitActorMirror().base_provide(topic, object);
  506. }
  507. /**
  508. * The <tt>when: topic discovered: handler</tt> construct. Pseudo-implementation:
  509. * <pre>actor.require(topic, handler, false)</pre>
  510. *
  511. * When an object is exported by <i>another</i> actor under topic, this construct triggers
  512. * the given code, passing a reference to the exported object as argument to the closure.
  513. *
  514. * Once the code block has run once, it will not be triggered again.
  515. *
  516. * @param topic the abstract 'subscription topic' used to find an exported object
  517. * @param handler a one-argument closure to apply to a discovered exported object
  518. * @return a subscription object whose <tt>cancel</tt> method can be used to cancel the subscription,
  519. * such that the handler will no longer be invoked. Beware, however, that at the time the
  520. * subscription is cancelled, a request to apply the closure may already have been scheduled
  521. * for execution by the current actor. This request is not cancelled by invoking the <tt>cancel</tt> method.
  522. */
  523. public ATObject base_when_discovered_(ATTypeTag topic, ATClosure handler) throws InterpreterException {
  524. return ELActor.currentActor().getImplicitActorMirror().base_require(topic, handler, NATBoolean._FALSE_);
  525. }
  526. /**
  527. * The <tt>whenever: topic discovered: handler</tt> construct. Pseudo-implementation:
  528. * <pre>actor.require(topic, handler, true)</pre>
  529. *
  530. * When an object is exported by <i>another</i> actor under topic, this construct triggers
  531. * the given code, passing a reference to the exported object as argument to the closure.
  532. *
  533. * The code block can be fired multiple times upon discovering multiple exported objects.
  534. * To stop the block from triggering upon new publications, it must be explicitly cancelled
  535. *
  536. * @param topic the abstract 'subscription topic' used to find an exported object
  537. * @param handler a one-argument closure to apply to any discovered exported object
  538. * @return a subscription object whose <tt>cancel</tt> method can be used to cancel the subscription,
  539. * such that the handler will no longer be invoked. Beware, however, that at the time the
  540. * subscription is cancelled, a request to apply the closure may already have been scheduled
  541. * for execution by the current actor. This request is not cancelled by invoking the <tt>cancel</tt> method.
  542. */
  543. public ATObject base_whenever_discovered_(ATTypeTag topic, ATClosure handler) throws InterpreterException {
  544. return ELActor.currentActor().getImplicitActorMirror().base_require(topic, handler, NATBoolean._TRUE_);
  545. }
  546. /**
  547. * The <tt>whenever: farReference disconnected: listener</tt> construct.
  548. * When the far reference is broken due to network disconnections, triggers the zero-arity listener
  549. * closure. It is possible to register listeners on local far references. These may trigger if the
  550. * local actor takes its object offline. In this case, these listeners will trigger as well.
  551. *
  552. * @param farReference a native far reference
  553. * @param listener a zero-arity closure to invoke if the far reference becomes disconnected
  554. * @return a subscription object whose <tt>cancel</tt> method can be used to cancel future
  555. * notifications of the listener.
  556. */
  557. public ATObject base_whenever_disconnected_(ATFarReference farReference, ATClosure listener) throws InterpreterException {
  558. farReference.asNativeFarReference().addDisconnectionListener(listener);
  559. return new NATFarReference.NATDisconnectionSubscription(farReference.asNativeFarReference(), listener);
  560. }
  561. /**
  562. * The <tt>whenever: farReference reconnected: listener</tt> construct.
  563. * When the remote reference is reinstated after a network disconnection, trigger the zero-arity
  564. * listener. Although it is allowed to register these listeners on local far references,
  565. * these are normally not invoked because the only possibility for a local far ref to become
  566. * disconnected is because the object was taken offline, and this is a permanent disconnect.
  567. *
  568. * @param farReference a native far reference
  569. * @param listener a zero-arity closure to invoke if the far reference becomes reconnected
  570. * @return a subscription object whose <tt>cancel</tt> method can be used to cancel future
  571. * notifications of the listener.
  572. */
  573. public ATObject base_whenever_reconnected_(ATFarReference farReference, ATClosure listener) throws InterpreterException {
  574. farReference.asNativeFarReference().addReconnectionListener(listener);
  575. return new NATFarReference.NATReconnectionSubscription(farReference.asNativeFarReference(), listener);
  576. }
  577. /**
  578. * The <tt>when: farReference takenOffline:</tt> construct.
  579. * When the (remote/local) far reference is broken because the object referenced was
  580. * taken offline, trigger the code.
  581. *
  582. * @param farReference a native far reference
  583. * @param listener a zero-arity closure to invoke if the referenced object has been taken offline.
  584. * @return a subscription object whose <tt>cancel</tt> method can be used to cancel future
  585. * notifications of the listener.
  586. */
  587. public ATObject base_when_takenOffline_(ATFarReference farReference, ATClosure listener) throws InterpreterException {
  588. farReference.asNativeFarReference().addTakenOfflineListener(listener);
  589. return new NATFarReference.NATExpiredSubscription(farReference.asNativeFarReference(), listener);
  590. }
  591. /**
  592. * The <tt>retract: farReference</tt> construct.
  593. * Retracts all currently unsent messages from the far reference's outbox.
  594. * This has the side effect that the returned messages will <b>not</b> be sent
  595. * automatically anymore, the programmer is responsible to explicitly resend
  596. * all messages that were retracted but still need to be sent.
  597. *
  598. * Note that the returned messages are copies of the original.
  599. * @param farReference the far reference of which to retract outgoing message sends
  600. * @return a table containing copies of all messages that were sent to this far reference, but
  601. * not yet transmitted by the far reference to its referent.
  602. */
  603. public ATTable base_retract_(ATFarReference farReference) throws InterpreterException {
  604. return farReference.meta_retractUnsentMessages();
  605. }
  606. /* -----------------------------
  607. * -- Object Creation Methods --
  608. * ----------------------------- */
  609. /**
  610. * The <tt>object:</tt> object creation primitive.
  611. * This construct creates a new AmbientTalk object where:
  612. * <ul>
  613. * <li>The object is initialized with the <i>code</i> of the argument closure.
  614. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  615. * <li>The object's <b>dynamic parent</b> is <tt>nil</tt>.
  616. * <li>The object's <b>parent type</b> is <b>SHARES-A</b> (i.e. it is not an extension of its parent).
  617. * <li>The object's <b>types</b> is <tt>[]</tt> (i.e. it has no types).
  618. * <li>The object's <b>mirror</b> is the <tt>defaultMirror</tt> on objects (i.e. it is an object
  619. * with a 'native' metaobject protocol).
  620. * </ul>
  621. *
  622. * Example: <code>object: { def x := 1; }</code>
  623. * <p>
  624. * Pseudo-implementation:
  625. * <pre>object: code childOf: nil extends: false taggedAs: [] mirroredBy: defaultMirror</pre>
  626. *
  627. * The closure used to initialize the object may contain formal parameters. The closure
  628. * will always be invoked with <i>its own mandatory formal parameters</i>. E.g., a closure
  629. * <code>{ |x| nil }</code> is invoked as <code>{ |x| nil }(x)</code>. The net effect of this
  630. * mechanic is that if <tt>x</tt> is a lexically visible variable at the object-creation
  631. * site, the value of the variable will be copied into a copy with the same name which
  632. * resides in the newly created object. This mechanic is primarily useful for copying surrounding
  633. * variables within the object, e.g. for isolates which lose access to their surrounding scope.
  634. * <p>
  635. * Also, if the closure has optional parameters, they will always be triggered.
  636. * The expressions to initialize the formal parameters are <i>evaluated</i>
  637. * in the context of the closure's lexical scope but are <i>added</i> to the newly created object.
  638. *
  639. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent
  640. * @return a new AmbientTalk object with the properties defined above.
  641. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  642. */
  643. public ATObject base_object_(ATClosure code) throws InterpreterException {
  644. return base_object_childOf_extends_taggedAs_mirroredBy_(
  645. code,
  646. Evaluator.getNil(),
  647. NATBoolean._FALSE_ /* SHARES-A link */,
  648. NATTable.EMPTY,
  649. base_defaultMirror());
  650. }
  651. /**
  652. * The <tt>extend:with:</tt> object creation primitive.
  653. * This construct creates a new AmbientTalk object where:
  654. * <ul>
  655. * <li>The object is initialized with the <i>code</i> of the argument closure.
  656. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  657. * <li>The object's <b>dynamic parent</b> is the argument object.
  658. * <li>The object's <b>parent type</b> is <b>IS-A</b> (i.e. it is an extension of its parent).
  659. * <li>The object's <b>types</b> is <tt>[]</tt> (i.e. it has no types).
  660. * <li>The object's <b>mirror</b> is the <tt>defaultMirror</tt> on objects (i.e. it is an object
  661. * with a 'native' metaobject protocol).
  662. * </ul>
  663. *
  664. * Example: <code>extend: parent with: { def x := 1; }</code>
  665. * <p>
  666. * Pseudo-implementation:
  667. * <pre>object: code childOf: parent extends: true taggedAs: [] mirroredBy: defaultMirror</pre>
  668. *
  669. * @param parent the dynamic parent object of the newly created object.
  670. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent
  671. * @return a new AmbientTalk object with the properties defined above.
  672. * @see #base_object_(ATClosure)
  673. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  674. */
  675. public ATObject base_extend_with_(ATObject parent, ATClosure code) throws InterpreterException {
  676. return base_object_childOf_extends_taggedAs_mirroredBy_(
  677. code,
  678. parent,
  679. NATBoolean._TRUE_ /* IS-A link */,
  680. NATTable.EMPTY,
  681. base_defaultMirror());
  682. }
  683. /**
  684. * The <tt>extend:with:taggedAs:</tt> object creation primitive.
  685. * This construct creates a new AmbientTalk object where:
  686. * <ul>
  687. * <li>The object is initialized with the <i>code</i> of the argument closure.
  688. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  689. * <li>The object's <b>dynamic parent</b> is the argument object.
  690. * <li>The object's <b>parent type</b> is <b>IS-A</b> (i.e. it is an extension of its parent).
  691. * <li>The object's <b>types</b> are initialized to the argument types table.
  692. * <li>The object's <b>mirror</b> is the <tt>defaultMirror</tt> on objects (i.e. it is an object
  693. * with a 'native' metaobject protocol).
  694. * </ul>
  695. *
  696. * Example: <code>extend: parent with: { def x := 1; } taggedAs: [foo,bar]</code>
  697. * <p>
  698. * Pseudo-implementation:
  699. * <pre>object: code childOf: parent extends: true taggedAs: types mirroredBy: defaultMirror</pre>
  700. *
  701. * @param parent the dynamic parent object of the newly created object.
  702. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  703. * @param types a table of types with which to type the newly created object.
  704. * @return a new AmbientTalk object with the properties defined above.
  705. * @see #base_object_(ATClosure)
  706. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  707. */
  708. public ATObject base_extend_with_taggedAs_(ATObject parent, ATClosure code, ATTable types) throws InterpreterException {
  709. return base_object_childOf_extends_taggedAs_mirroredBy_(
  710. code,
  711. parent,
  712. NATBoolean._TRUE_ /* IS-A link */,
  713. types,
  714. base_defaultMirror());
  715. }
  716. /**
  717. * The <tt>extend:with:mirroredBy:</tt> object creation primitive.
  718. * This construct creates a new AmbientTalk object where:
  719. * <ul>
  720. * <li>The object is initialized with the <i>code</i> of the argument closure.
  721. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  722. * <li>The object's <b>dynamic parent</b> is the argument object.
  723. * <li>The object's <b>parent type</b> is <b>IS-A</b> (i.e. it is an extension of its parent).
  724. * <li>The object's <b>types</b> are set to <tt>[]</tt> (i.e. the object has no types).
  725. * <li>The object's <b>mirror</b> is the given mirror. This means that this object is a <i>mirage</i>
  726. * whose metaobject protocol is entirely dictated by the given mirror.
  727. * </ul>
  728. *
  729. * Example: <code>extend: parent with: { def x := 1; } mirroredBy: (mirror: {...})</code>
  730. * <p>
  731. * Pseudo-implementation:
  732. * <pre>object: code childOf: parent extends: true taggedAs: [] mirroredBy: mirror</pre>
  733. *
  734. * @param parent the dynamic parent object of the newly created object.
  735. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  736. * @param mirror the mirror of the newly created mirage object.
  737. * @return a new AmbientTalk object with the properties defined above.
  738. * @see #base_object_(ATClosure)
  739. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  740. */
  741. public ATObject base_extend_with_mirroredBy_(ATObject parent, ATClosure code, ATObject mirror) throws InterpreterException {
  742. return base_object_childOf_extends_taggedAs_mirroredBy_(
  743. code,
  744. parent,
  745. NATBoolean._TRUE_ /* IS-A link */,
  746. NATTable.EMPTY,
  747. mirror);
  748. }
  749. /**
  750. * The <tt>extend:with:taggedAs:mirroredBy:</tt> object creation primitive.
  751. * This construct creates a new AmbientTalk object where:
  752. * <ul>
  753. * <li>The object is initialized with the <i>code</i> of the argument closure.
  754. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  755. * <li>The object's <b>dynamic parent</b> is the argument object.
  756. * <li>The object's <b>parent type</b> is <b>IS-A</b> (i.e. it is an extension of its parent).
  757. * <li>The object's <b>types</b> are initialized to the argument types table.
  758. * <li>The object's <b>mirror</b> is the given argument mirror. This means that the newly
  759. * created object is a <i>mirage</i> whose metaobject protocol is dictated by the given mirror.
  760. * </ul>
  761. *
  762. * Example: <code>extend: parent with: { def x := 1; } taggedAs: [foo,bar] mirroredBy: mirror</code>
  763. * <p>
  764. * Pseudo-implementation:
  765. * <pre>object: code childOf: parent extends: true taggedAs: types mirroredBy: mirror</pre>
  766. *
  767. * @param parent the dynamic parent object of the newly created object.
  768. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  769. * @param types a table of types with which to type the newly created object.
  770. * @param the mirror object of the newly created mirage object.
  771. * @return a new AmbientTalk object with the properties defined above.
  772. * @see #base_object_(ATClosure)
  773. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  774. */
  775. public ATObject base_extend_with_taggedAs_mirroredBy_(ATObject parent, ATClosure code, ATTable types, ATObject mirror) throws InterpreterException {
  776. return base_object_childOf_extends_taggedAs_mirroredBy_(
  777. code,
  778. parent,
  779. NATBoolean._TRUE_ /* IS-A link */,
  780. types,
  781. mirror);
  782. }
  783. /**
  784. * The <tt>share:with:</tt> object creation primitive.
  785. * This construct creates a new AmbientTalk object where:
  786. * <ul>
  787. * <li>The object is initialized with the <i>code</i> of the argument closure.
  788. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  789. * <li>The object's <b>dynamic parent</b> is the argument object.
  790. * <li>The object's <b>parent type</b> is <b>SHARES-A</b> (i.e. it is not an extension of its parent).
  791. * <li>The object's <b>types</b> is <tt>[]</tt> (i.e. it has no types).
  792. * <li>The object's <b>mirror</b> is the <tt>defaultMirror</tt> on objects (i.e. it is an object
  793. * with a 'native' metaobject protocol).
  794. * </ul>
  795. *
  796. * Example: <code>share: parent with: { def x := 1; }</code>
  797. * <p>
  798. * Pseudo-implementation:
  799. * <pre>object: code childOf: parent extends: false taggedAs: [] mirroredBy: defaultMirror</pre>
  800. *
  801. * @param parent the dynamic parent object of the newly created object.
  802. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent
  803. * @return a new AmbientTalk object with the properties defined above.
  804. * @see #base_object_(ATClosure)
  805. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  806. */
  807. public ATObject base_share_with_(ATObject parent, ATClosure code) throws InterpreterException {
  808. return base_object_childOf_extends_taggedAs_mirroredBy_(
  809. code,
  810. parent,
  811. NATBoolean._FALSE_ /* SHARES-A link */,
  812. NATTable.EMPTY,
  813. base_defaultMirror());
  814. }
  815. /**
  816. * The <tt>share:with:taggedAs:</tt> object creation primitive.
  817. * This construct creates a new AmbientTalk object where:
  818. * <ul>
  819. * <li>The object is initialized with the <i>code</i> of the argument closure.
  820. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  821. * <li>The object's <b>dynamic parent</b> is the argument object.
  822. * <li>The object's <b>parent type</b> is <b>SHARES-A</b> (i.e. it is not an extension of its parent).
  823. * <li>The object's <b>types</b> are initialized to the argument types table.
  824. * <li>The object's <b>mirror</b> is the <tt>defaultMirror</tt> on objects (i.e. it is an object
  825. * with a 'native' metaobject protocol).
  826. * </ul>
  827. *
  828. * Example: <code>share: parent with: { def x := 1; } taggedAs: [foo,bar]</code>
  829. * <p>
  830. * Pseudo-implementation:
  831. * <pre>object: code childOf: parent extends: false taggedAs: types mirroredBy: defaultMirror</pre>
  832. *
  833. * @param parent the dynamic parent object of the newly created object.
  834. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  835. * @param types a table of types with which to type the newly created object.
  836. * @return a new AmbientTalk object with the properties defined above.
  837. * @see #base_object_(ATClosure)
  838. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  839. */
  840. public ATObject base_share_with_taggedAs_(ATObject parent, ATClosure code, ATTable types) throws InterpreterException {
  841. return base_object_childOf_extends_taggedAs_mirroredBy_(
  842. code,
  843. parent,
  844. NATBoolean._FALSE_ /* SHARES-A link */,
  845. types,
  846. base_defaultMirror());
  847. }
  848. /**
  849. * The <tt>share:with:mirroredBy:</tt> object creation primitive.
  850. * This construct creates a new AmbientTalk object where:
  851. * <ul>
  852. * <li>The object is initialized with the <i>code</i> of the argument closure.
  853. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  854. * <li>The object's <b>dynamic parent</b> is the argument object.
  855. * <li>The object's <b>parent type</b> is <b>SHARES-A</b> (i.e. it is not an extension of its parent).
  856. * <li>The object's <b>types</b> are set to <tt>[]</tt> (i.e. the object has no types).
  857. * <li>The object's <b>mirror</b> is the given mirror. This means that this object is a <i>mirage</i>
  858. * whose metaobject protocol is entirely dictated by the given mirror.
  859. * </ul>
  860. *
  861. * Example: <code>share: parent with: { def x := 1; } mirroredBy: (mirror: {...})</code>
  862. * <p>
  863. * Pseudo-implementation:
  864. * <pre>object: code childOf: parent extends: false taggedAs: [] mirroredBy: mirror</pre>
  865. *
  866. * @param parent the dynamic parent object of the newly created object.
  867. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  868. * @param mirror the mirror of the newly created mirage object.
  869. * @return a new AmbientTalk object with the properties defined above.
  870. * @see #base_object_(ATClosure)
  871. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  872. */
  873. public ATObject base_share_with_mirroredBy_(ATObject parent, ATClosure code, ATObject mirror) throws InterpreterException {
  874. return base_object_childOf_extends_taggedAs_mirroredBy_(
  875. code,
  876. parent,
  877. NATBoolean._FALSE_ /* SHARES-A link */,
  878. NATTable.EMPTY,
  879. mirror);
  880. }
  881. /**
  882. * The <tt>share:with:taggedAs:mirroredBy:</tt> object creation primitive.
  883. * This construct creates a new AmbientTalk object where:
  884. * <ul>
  885. * <li>The object is initialized with the <i>code</i> of the argument closure.
  886. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  887. * <li>The object's <b>dynamic parent</b> is the argument object.
  888. * <li>The object's <b>parent type</b> is <b>SHARES-A</b> (i.e. it is not an extension of its parent).
  889. * <li>The object's <b>types</b> are initialized to the argument types table.
  890. * <li>The object's <b>mirror</b> is the given argument mirror. This means that the newly
  891. * created object is a <i>mirage</i> whose metaobject protocol is dictated by the given mirror.
  892. * </ul>
  893. *
  894. * Example: <code>share: parent with: { def x := 1; } taggedAs: [foo,bar] mirroredBy: mirror</code>
  895. * <p>
  896. * Pseudo-implementation:
  897. * <pre>object: code childOf: parent extends: false taggedAs: types mirroredBy: mirror</pre>
  898. *
  899. * @param parent the dynamic parent object of the newly created object.
  900. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  901. * @param types a table of types with which to type the newly created object.
  902. * @param mirror the mirror object of the newly created mirage object.
  903. * @return a new AmbientTalk object with the properties defined above.
  904. * @see #base_object_(ATClosure)
  905. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  906. */
  907. public ATObject base_share_with_taggedAs_mirroredBy_(ATObject parent, ATClosure code, ATTable types, ATObject mirror) throws InterpreterException {
  908. return base_object_childOf_extends_taggedAs_mirroredBy_(
  909. code,
  910. parent,
  911. NATBoolean._FALSE_ /* SHARES-A link */,
  912. types,
  913. mirror);
  914. }
  915. /**
  916. * The <tt>object:taggedAs:</tt> object creation primitive.
  917. * This construct creates a new AmbientTalk object where:
  918. * <ul>
  919. * <li>The object is initialized with the <i>code</i> of the argument closure.
  920. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  921. * <li>The object's <b>dynamic parent</b> is <tt>nil</tt>.
  922. * <li>The object's <b>parent type</b> is <b>SHARES-A</b> (i.e. it is not an extension of its parent).
  923. * <li>The object's <b>types</b> are initialized to the argument types table.
  924. * <li>The object's <b>mirror</b> is <tt>defaultMirror</tt> (i.e. the object has the
  925. * default metaobject protocol).
  926. * </ul>
  927. *
  928. * Example: <code>object: { def x := 1; } taggedAs: [foo,bar]</code>
  929. * <p>
  930. * Pseudo-implementation:
  931. * <pre>object: code childOf: nil extends: false taggedAs: types mirroredBy: defaultMirror</pre>
  932. *
  933. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  934. * @param types a table of type tags with which to type the newly created object.
  935. * @return a new AmbientTalk object with the properties defined above.
  936. * @see #base_object_(ATClosure)
  937. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  938. */
  939. public ATObject base_object_taggedAs_(ATClosure code, ATTable types) throws InterpreterException {
  940. return base_object_childOf_extends_taggedAs_mirroredBy_(
  941. code,
  942. Evaluator.getNil(),
  943. NATBoolean._FALSE_ /* SHARES-A link */,
  944. types,
  945. base_defaultMirror());
  946. }
  947. /**
  948. * The <tt>isolate:</tt> object creation primitive.
  949. * This construct creates a new AmbientTalk object where:
  950. * <ul>
  951. * <li>The object is initialized with the <i>code</i> of the argument closure.
  952. * <li>The object's <b>lexical parent</b> is initialized to the lexical scope of the argument closure,
  953. * but because it is typed as an isolate, the parent link is replaced by a link to the lexical <tt>root</tt>.
  954. * <li>The object's <b>dynamic parent</b> is <tt>nil</tt>.
  955. * <li>The object's <b>parent type</b> is <b>SHARES-A</b> (i.e. it is not an extension of its parent).
  956. * <li>The object's <b>types</b> are initialized to <tt>[/.at.types.Isolate]</tt>, i.e.
  957. * the object is typed as an isolate.
  958. * <li>The object's <b>mirror</b> is <tt>defaultMirror</tt> (i.e. the object has the
  959. * default metaobject protocol).
  960. * </ul>
  961. *
  962. * Example: <code>isolate: { def x := 1; }</code>
  963. * <p>
  964. * Pseudo-implementation:
  965. * <pre>object: code childOf: nil extends: false taggedAs: [/.at.types.Isolate] mirroredBy: defaultMirror</pre>
  966. *
  967. * An isolate is an object without a proper lexical parent. It is as if the isolate is always
  968. * defined at top-level. However, lexically visible variables can be retained by copying them into the isolate
  969. * by means of formal parameters to the argument closure. Isolate objects are passed by-copy during
  970. * inter-actor parameter and result passing.
  971. *
  972. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  973. * @return a new AmbientTalk object with the properties defined above.
  974. * @see #base_object_(ATClosure)
  975. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  976. */
  977. public ATObject base_isolate_(ATClosure code) throws InterpreterException {
  978. return base_object_taggedAs_(code, NATTable.of(NativeTypeTags._ISOLATE_));
  979. }
  980. /**
  981. * The <tt>mirror:</tt> object creation primitive.
  982. * This construct creates a new AmbientTalk object where:
  983. * <ul>
  984. * <li>The object is initialized with the <i>code</i> of the argument closure.
  985. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  986. * <li>The object's <b>dynamic parent</b> is <tt>defaultMirror</tt>.
  987. * <li>The object's <b>parent type</b> is <b>IS-A</b> (i.e. it is an extension of its parent).
  988. * <li>The object's <b>types</b> are initialized to <tt>[]</tt>.
  989. * <li>The object's <b>mirror</b> is <tt>defaultMirror</tt> (i.e. the object has the
  990. * default metaobject protocol).
  991. * </ul>
  992. *
  993. * Example: <code>mirror: { def x := 1; }</code>
  994. * <p>
  995. * Pseudo-implementation:
  996. * <pre>object: code childOf: defaultMirror extends: true taggedAs: [] mirroredBy: defaultMirror</pre>
  997. *
  998. * This construct is mere syntactic sugar for creating an extension of the default mirror root.
  999. * It follows that AmbientTalk mirrors are plain AmbientTalk objects. They simply need to implement
  1000. * the entire metaobject protocol, and the easiest means to achieve this is by extending the default mirror.
  1001. * Also keep in mind that the mirror is an extension object. This is important because the default
  1002. * mirror has <i>state</i>, being the <tt>base</tt> field that points to the base-level object
  1003. * being mirrorred. Hence, always make sure that, if overriding <tt>init</tt>, the parent's
  1004. * <tt>init</tt> method is invoked with the appropriate <tt>base</tt> value.
  1005. *
  1006. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  1007. * @return a new AmbientTalk object with the properties defined above.
  1008. * @see #base_object_(ATClosure)
  1009. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  1010. */
  1011. public ATObject base_mirror_(ATClosure code) throws InterpreterException {
  1012. return base_object_childOf_extends_taggedAs_mirroredBy_(
  1013. code,
  1014. base_defaultMirror(),
  1015. NATBoolean._TRUE_ /* IS-A link */,
  1016. NATTable.EMPTY,
  1017. base_defaultMirror());
  1018. }
  1019. /**
  1020. * The <tt>object:mirroredBy:</tt> object creation primitive.
  1021. * This construct creates a new AmbientTalk object where:
  1022. * <ul>
  1023. * <li>The object is initialized with the <i>code</i> of the argument closure.
  1024. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  1025. * <li>The object's <b>dynamic parent</b> is <tt>nil</tt>.
  1026. * <li>The object's <b>parent type</b> is <b>SHARES-A</b> (i.e. it is not an extension of its parent).
  1027. * <li>The object's <b>types</b> are set to <tt>[]</tt> (i.e. the object has no types).
  1028. * <li>The object's <b>mirror</b> is the given mirror. This means that this object is a <i>mirage</i>
  1029. * whose metaobject protocol is entirely dictated by the given mirror.
  1030. * </ul>
  1031. *
  1032. * Example: <code>object: { def x := 1; } mirroredBy: (mirror: {...})</code>
  1033. * <p>
  1034. * Pseudo-implementation:
  1035. * <pre>object: code childOf: nil extends: false taggedAs: [] mirroredBy: mirror</pre>
  1036. *
  1037. * This primitive allows the construction of so-called <i>mirage</i> objects which are
  1038. * AmbientTalk objects whose metaobject protocol behaviour is dictated by a custom mirror
  1039. * object.
  1040. *
  1041. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  1042. * @param mirror the mirror prototype of the newly created mirage object, or a constructor closure.
  1043. * @return a new AmbientTalk object with the properties defined above.
  1044. * @see #base_object_(ATClosure)
  1045. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  1046. */
  1047. public ATObject base_object_mirroredBy_(ATClosure code, ATObject mirror) throws InterpreterException {
  1048. return base_object_childOf_extends_taggedAs_mirroredBy_(
  1049. code,
  1050. Evaluator.getNil(),
  1051. NATBoolean._FALSE_ /* SHARES-A link */,
  1052. NATTable.EMPTY,
  1053. mirror);
  1054. }
  1055. /**
  1056. * The <tt>object:taggedAs:mirroredBy:</tt> object creation primitive.
  1057. * This construct creates a new AmbientTalk object where:
  1058. * <ul>
  1059. * <li>The object is initialized with the <i>code</i> of the argument closure.
  1060. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  1061. * <li>The object's <b>dynamic parent</b> is <tt>nil</tt>.
  1062. * <li>The object's <b>parent type</b> is <b>SHARES-A</b> (i.e. it is not an extension of its parent).
  1063. * <li>The object's <b>types</b> are set to the argument types.
  1064. * <li>The object's <b>mirror</b> is a clone of given mirror, or the return value of a constructor closure. This means that this object is a <i>mirage</i>
  1065. * whose metaobject protocol is entirely dictated by the given mirror.
  1066. * </ul>
  1067. *
  1068. * Example: <code>object: { def x := 1; } taggedAs: [foo,bar] mirroredBy: (mirror: {...})</code>
  1069. * <p>
  1070. * Pseudo-implementation:
  1071. * <pre>object: code childOf: nil extends: false taggedAs: types mirroredBy: mirror</pre>
  1072. *
  1073. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  1074. * @param types a table of types with which to type the newly created object.
  1075. * @param mirror the mirror of the newly created mirage object.
  1076. * @return a new AmbientTalk object with the properties defined above.
  1077. * @see #base_object_(ATClosure)
  1078. * @see #base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure, ATObject, ATBoolean, ATTable, ATObject)
  1079. */
  1080. public ATObject base_object_taggedAs_mirroredBy_(ATClosure code, ATTable types, ATObject mirror) throws InterpreterException {
  1081. return base_object_childOf_extends_taggedAs_mirroredBy_(
  1082. code,
  1083. Evaluator.getNil(),
  1084. NATBoolean._FALSE_ /* SHARES-A link */,
  1085. types,
  1086. mirror);
  1087. }
  1088. /**
  1089. * The <tt>object:childOf:extends:taggedAs:mirroredBy:</tt> object creation primitive.
  1090. * This construct creates a new AmbientTalk object where:
  1091. * <ul>
  1092. * <li>The object is initialized with the <i>code</i> of the argument closure.
  1093. * <li>The object's <b>lexical parent</b> is the lexical scope of the argument closure.
  1094. * <li>The object's <b>dynamic parent</b> is the argument parent object.
  1095. * <li>The object's <b>parent type</b> is the argument parent type, true being <tt>IS-A</tt>, false being <tt>SHARES-A</tt>.
  1096. * <li>The object's <b>types</b> are set to the argument types table.
  1097. * <li>The object's <b>mirror</b> is a clone of the given mirror prototype,
  1098. * or the return value of the given constructor closure. This means that this object is a <i>mirage</i>
  1099. * whose metaobject protocol is entirely dictated by the given mirror, if the mirror is not <tt>defaultMirror</tt>.
  1100. * </ul>
  1101. *
  1102. * Example: <code>object: { def x := 1; } childOf: parent extends: true taggedAs: [foo,bar] mirroredBy: mirror</code>
  1103. * <p>
  1104. * Pseudo-implementation:
  1105. * <pre>let o = OBJECT(parent,code.lexicalParent,parentType,types);
  1106. * code.applyInScope(o, code.mandatoryPars);
  1107. * o
  1108. * </pre>
  1109. *
  1110. * @param code a closure containing both the code with which to initialize the object and the new object's lexical parent.
  1111. * @param parent the dynamic parent object of the newly created object.
  1112. * @param parentType a boolean denoting whether or not the object is an extension of its dynamic parent.
  1113. * @param types a table of types with which the newly created object should be typed.
  1114. * @param mirror the mirror of the newly created object.
  1115. * @return a new AmbientTalk object with the properties defined above.
  1116. * @see #base_object_(ATClosure) for more information about the properties of the passed closure.
  1117. */
  1118. public ATObject base_object_childOf_extends_taggedAs_mirroredBy_(ATClosure code, ATObject parent, ATBoolean parentType, ATTable types, ATObject mirror) throws InterpreterException {
  1119. ATTypeTag[] typeArray = NATTypeTag.toTypeTagArray(types);
  1120. boolean parentRelation = parentType.asNativeBoolean().javaValue;
  1121. NATObject newObject;
  1122. // if the mirror is a 'default' mirror...
  1123. if (mirror instanceof NATMirrorRoot) {
  1124. // then create a native object
  1125. newObject = new NATObject(parent, // dynamic parent
  1126. code.base_context().base_lexicalScope(), // lexical parent
  1127. parentRelation, // IS-A or SHARES-A
  1128. typeArray); // initial types
  1129. } else {
  1130. // else create a mirage mirrored by the custom mirror
  1131. newObject = NATMirage.createMirage(code, parent, parentRelation, typeArray, mirror);
  1132. }
  1133. newObject.initializeWithCode(code);
  1134. return newObject;
  1135. }
  1136. /**
  1137. * The <tt>reflect:</tt> construct. This construct returns a mirror on an object.
  1138. *
  1139. * pseudo-implementation:
  1140. * <pre>actor.createMirror(reflectee)</pre>
  1141. *
  1142. * An actor can change its default mirror creation policy by installing a new
  1143. * actor protocol that overrides <tt>createMirror</tt>.
  1144. *
  1145. * @param reflectee the object to reflect upon
  1146. * @return a mirror reflecting on the given object
  1147. * @see ATActorMirror#base_createMirror(ATObject) for the details about mirror creation on objects.
  1148. */
  1149. public ATObject base_reflect_(ATObject reflectee) throws InterpreterException {
  1150. return base_reflectOnActor().base_createMirror(reflectee);
  1151. }
  1152. /**
  1153. * The <tt>clone:</tt> language construct. Returns a clone of an object.
  1154. *
  1155. * Care must be taken when cloning a mirror. If a mirror would simply be cloned
  1156. * using the regular cloning semantics, its base field would be <b>shared</b>
  1157. * between the clone and the original mirror (because of shallow copy semantics).
  1158. * However, the base object will still be tied to the original mirror, not the clone.
  1159. * Therefore, the clone: operator is implemented as follows:
  1160. *
  1161. * <pre>def clone: obj {
  1162. * if: (is: obj taggedAs: Mirror) then: {
  1163. * reflect: (clone: obj.base)
  1164. * } else: {
  1165. * (reflect: obj).clone()
  1166. * }
  1167. * }</pre>
  1168. *
  1169. * The default cloning semantics ensures that all fields of the object are shallow-copied.
  1170. * Because methods are immutable, a clone and its original object share their method dictionary,
  1171. * but whenever a change is made to the dictionary, the changer creates a local copy of the
  1172. * dictionary as to not modify any clones. Hence, each object is truly stand-alone and independent
  1173. * of its clone.
  1174. *
  1175. * @param original the object to copy
  1176. * @return a clone of the given object (default semantics results in a shallow copy)
  1177. */
  1178. public ATObject base_clone_(ATObject original) throws InterpreterException {
  1179. if (original.meta_isTaggedAs(NativeTypeTags._MIRROR_).asNativeBoolean().javaValue) {
  1180. return base_reflect_(base_clone_(original.impl_invokeAccessor(original, NATMirrorRoot._BASE_NAME_, NATTable.EMPTY)));
  1181. } else {
  1182. return original.meta_clone();
  1183. }
  1184. }
  1185. /**
  1186. * The <tt>takeOffline:</tt> construct.
  1187. * Removes an object from the export table of an actor. This ensures that the object
  1188. * is no longer remotely accessible. This method is the cornerstone of distributed
  1189. * garbage collection in AmbientTalk. When an object is taken offline, remote clients
  1190. * that would still access it perceive this as if the object had become permanently
  1191. * disconnected.
  1192. *
  1193. * @return <tt>nil</tt>.
  1194. */
  1195. public ATNil base_takeOffline_ (ATObject object) throws InterpreterException{
  1196. ELActor.currentActor().takeOffline(object);
  1197. return Evaluator.getNil();
  1198. }
  1199. /* -------------------
  1200. * -- Type Support -
  1201. * ------------------- */
  1202. /**
  1203. * The <tt>is: object taggedAs: type</tt> construct.
  1204. * @return true if the given object is typed with the given type, false otherwise
  1205. */
  1206. public ATBoolean base_is_taggedAs_(ATObject object, ATTypeTag type) throws InterpreterException {
  1207. return object.meta_isTaggedAs(type);
  1208. }
  1209. /**
  1210. * The <tt>tagsOf: object</tt> construct.
  1211. * @return a table of all of the <i>local</i> types of an object.
  1212. */
  1213. public ATTable base_tagsOf_(ATObject object) throws InterpreterException {
  1214. return object.meta_typeTags();
  1215. }
  1216. /* -------------------------------
  1217. * -- Exception Handling Support -
  1218. * ------------------------------- */
  1219. /**
  1220. * The <tt>try: { tryBlock } finally: { finallyBlock }</tt> construct.
  1221. *
  1222. * Applies the tryBlock closure (to <tt>[]</tt>).
  1223. * Whether the tryBlock raises an exception or not, the finallyBlock closure is guaranteed to be applied either
  1224. * after normal termination of the tryBlock or when an exception is propagated from the tryBlock.
  1225. */
  1226. public ATObject base_try_finally_(ATClosure tryBlock, ATClosure finallyBlock) throws InterpreterException {
  1227. try {
  1228. return tryBlock.base_apply(NATTable.EMPTY);
  1229. } finally {
  1230. finallyBlock.base_apply(NATTable.EMPTY);
  1231. }
  1232. }
  1233. /**
  1234. * The <tt>try: { tryBlock } usingHandlers: [ handler1, handler2, ... ] finally: { finallyBlock }</tt> construct.
  1235. *
  1236. * Applies the tryBlock closure (to <tt>[]</tt>) and handles exceptions using the given exception handlers.
  1237. * Whether the tryBlock raises an exception or not, the finallyBlock closure is guaranteed to be applied either
  1238. * after the termination of the tryBlock or the execution of a fitting handler either before the exception is
  1239. * propagated if no matching handler is provided. This construct is the most general means of doing exception
  1240. * handling in AmbientTalk.
  1241. *
  1242. * The handlers given in the handler table represent first-class handler objects,
  1243. * which should respond to the <tt>canHandle</tt> message.
  1244. * @see ATHandler for the interface to which a handler object has to adhere
  1245. */
  1246. public ATObject base_try_usingHandlers_finally_(ATClosure tryBlock, ATTable exceptionHandlers, ATClosure finallyBlock) throws InterpreterException {
  1247. try {
  1248. return tryBlock.base_apply(NATTable.EMPTY);
  1249. } catch(InterpreterException e) {
  1250. ATObject[] handlers = exceptionHandlers.asNativeTable().elements_;
  1251. // find the appropriate handler
  1252. for (int i = 0; i < handlers.length; i++) {
  1253. ATHandler handler = handlers[i].asHandler();
  1254. ATObject exc = e.getAmbientTalkRepresentation();
  1255. if (handler.base_canHandle(exc).asNativeBoolean().javaValue) {
  1256. return handler.base_handle(exc);
  1257. };
  1258. }
  1259. // no handler found, re-throw the exception
  1260. throw e;
  1261. } finally {
  1262. finallyBlock.base_apply(NATTable.EMPTY);
  1263. }
  1264. }
  1265. /**
  1266. * The <tt>try: { tryBlock } usingHandlers: [ handler1, handler2, ... ]</tt> construct.
  1267. *
  1268. * Ad hoc code for tryBlocks which have an empty finally block
  1269. * @see OBJLexicalRoot#base_try_usingHandlers_finally_(ATClosure, ATTable, ATClosure)
  1270. */
  1271. public ATObject base_try_usingHandlers_(ATClosure tryBlock, ATTable exceptionHandlers) throws InterpreterException {
  1272. // An ad hoc version is provided since not using a finally block is a lot cheaper
  1273. // when we know for sure we won't be needing one.
  1274. try {
  1275. return tryBlock.base_apply(NATTable.EMPTY);
  1276. } catch(InterpreterException e) {
  1277. ATObject[] handlers = exceptionHandlers.asNativeTable().elements_;
  1278. // find the appropriate handler
  1279. for (int i = 0; i < handlers.length; i++) {
  1280. ATHandler handler = handlers[i].asHandler();
  1281. ATObject exc = e.getAmbientTalkRepresentation();
  1282. if (handler.base_canHandle(exc).asNativeBoolean().javaValue) {
  1283. return handler.base_handle(exc);
  1284. };
  1285. }
  1286. // no handler found, re-throw the exception
  1287. throw e;
  1288. }
  1289. }
  1290. /**
  1291. * The <tt>try: { tryBlock} using: handler</tt> construct.
  1292. *
  1293. * Ad-hoc code for one exception handler.
  1294. *
  1295. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1296. */
  1297. public ATObject base_try_using_(ATClosure tryBlock, ATHandler handler) throws InterpreterException {
  1298. try {
  1299. return tryBlock.base_apply(NATTable.EMPTY);
  1300. } catch(InterpreterException e) {
  1301. ATObject exc = e.getAmbientTalkRepresentation();
  1302. if (handler.base_canHandle(exc).asNativeBoolean().javaValue) {
  1303. return handler.base_handle(exc);
  1304. } else {
  1305. throw e;
  1306. }
  1307. }
  1308. }
  1309. /**
  1310. * The <tt>try: { tryBlock} using: handler finally: { finallyBlock }</tt> construct.
  1311. *
  1312. * Ad-hoc code for one exception handler.
  1313. *
  1314. * @see #base_try_usingHandlers_finally_(ATClosure, ATTable, ATClosure)
  1315. */
  1316. public ATObject base_try_using_finally_(ATClosure tryBlock, ATHandler handler, ATClosure finallyBlock) throws InterpreterException {
  1317. try {
  1318. return tryBlock.base_apply(NATTable.EMPTY);
  1319. } catch(InterpreterException e) {
  1320. ATObject exc = e.getAmbientTalkRepresentation();
  1321. if (handler.base_canHandle(exc).asNativeBoolean().javaValue) {
  1322. return handler.base_handle(exc);
  1323. } else {
  1324. throw e;
  1325. }
  1326. } finally {
  1327. finallyBlock.base_apply(NATTable.EMPTY);
  1328. }
  1329. }
  1330. /**
  1331. * The <tt>try: { tryBlock} using: handler1 using: handler2</tt> construct.
  1332. *
  1333. * Ad-hoc code for two exception handlers.
  1334. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1335. */
  1336. public ATObject base_try_using_using_(ATClosure tryBlock, ATHandler hdl1, ATHandler hdl2) throws InterpreterException {
  1337. return base_try_usingHandlers_(tryBlock, NATTable.atValue(new ATObject[] { hdl1, hdl2 }));
  1338. }
  1339. /**
  1340. * The <tt>try: { tryBlock} using: handler1 using: handler2 finally: { finallyBlock }</tt> construct.
  1341. *
  1342. * Ad-hoc code for two exception handlers.
  1343. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1344. */
  1345. public ATObject base_try_using_using_finally_(ATClosure tryBlock, ATHandler hdl1, ATHandler hdl2, ATClosure finallyBlock) throws InterpreterException {
  1346. return base_try_usingHandlers_finally_(tryBlock, NATTable.atValue(new ATObject[] { hdl1, hdl2 }), finallyBlock);
  1347. }
  1348. /**
  1349. * The <tt>try: { tryBlock} using: hdl1 using: hdl2 using: hdl3</tt> construct.
  1350. *
  1351. * Ad-hoc code for three exception handlers
  1352. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1353. */
  1354. public ATObject base_try_using_using_using_(ATClosure tryBlock, ATHandler hdl1, ATHandler hdl2, ATHandler hdl3) throws InterpreterException {
  1355. return base_try_usingHandlers_(tryBlock, NATTable.atValue(new ATObject[] { hdl1, hdl2, hdl3 }));
  1356. }
  1357. /**
  1358. * The <tt>try: { tryBlock} using: hdl1 using: hdl2 using: hdl3 finally: { finallyBlock }</tt> construct.
  1359. *
  1360. * Ad-hoc code for three exception handlers.
  1361. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1362. */
  1363. public ATObject base_try_using_using_using_finally_(ATClosure tryBlock, ATHandler hdl1, ATHandler hdl2, ATHandler hdl3, ATClosure finallyBlock) throws InterpreterException {
  1364. return base_try_usingHandlers_finally_(tryBlock, NATTable.atValue(new ATObject[] { hdl1, hdl2, hdl3 }), finallyBlock);
  1365. }
  1366. /**
  1367. * The <tt>try: { tryBlock} catch: type using: { |e| replacementCode }</tt>
  1368. *
  1369. * 'Syntactic sugar' for one "in-line", native handler.
  1370. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1371. */
  1372. public ATObject base_try_catch_using_(ATClosure tryBlock, ATTypeTag filter, ATClosure replacementCode) throws InterpreterException {
  1373. return base_try_using_(tryBlock, new NATHandler(filter, replacementCode));
  1374. }
  1375. /**
  1376. * The <tt>try: { tryBlock} catch: type using: { |e| replacementCode } finally: { finallyBlock }</tt>
  1377. *
  1378. * 'Syntactic sugar' for one "in-line", native handler.
  1379. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1380. */
  1381. public ATObject base_try_catch_using_finally_(ATClosure tryBlock, ATTypeTag filter, ATClosure replacementCode, ATClosure finallyBlock) throws InterpreterException {
  1382. return base_try_using_finally_(tryBlock, new NATHandler(filter, replacementCode), finallyBlock);
  1383. }
  1384. /**
  1385. * The <tt>try:catch:using:catch:using:</tt> construct.
  1386. *
  1387. * <pre>try: {
  1388. * tryBlock
  1389. * } catch: type using: { |e|
  1390. * replacementCode
  1391. * } catch: type2 using: { |e|
  1392. * replacementCode2
  1393. * }</pre>
  1394. *
  1395. * 'Syntactic sugar' for two in-line handlers
  1396. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1397. */
  1398. public ATObject base_try_catch_using_catch_using_( ATClosure tryBlock,
  1399. ATTypeTag filter1, ATClosure hdl1,
  1400. ATTypeTag filter2, ATClosure hdl2) throws InterpreterException {
  1401. return base_try_using_using_(tryBlock, new NATHandler(filter1, hdl1), new NATHandler(filter2, hdl2));
  1402. }
  1403. /**
  1404. * The <tt>try:catch:using:catch:using:finally:</tt> construct.
  1405. *
  1406. * <pre>try: {
  1407. * tryBlock
  1408. * } catch: type using: { |e|
  1409. * replacementCode
  1410. * } catch: type2 using: { |e|
  1411. * replacementCode2
  1412. * } finally: {
  1413. * finalizationCode
  1414. * }</pre>
  1415. *
  1416. * 'Syntactic sugar' for two in-line handlers
  1417. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1418. */
  1419. public ATObject base_try_catch_using_catch_using_finally_( ATClosure tryBlock,
  1420. ATTypeTag filter1, ATClosure hdl1,
  1421. ATTypeTag filter2, ATClosure hdl2,
  1422. ATClosure finallyBlock) throws InterpreterException {
  1423. return base_try_using_using_finally_(tryBlock, new NATHandler(filter1, hdl1), new NATHandler(filter2, hdl2), finallyBlock);
  1424. }
  1425. /**
  1426. * The <tt>try:catch:using:catch:using:catch:using:</tt> construct.
  1427. *
  1428. * <pre>try: {
  1429. * tryBlock
  1430. * } catch: type using: { |e|
  1431. * replacementCode
  1432. * } catch: type2 using: { |e|
  1433. * replacementCode2
  1434. * } catch: type3 using: { |e|
  1435. * replacementCode3
  1436. * }</pre>
  1437. *
  1438. * 'Syntactic sugar' for three in-line handlers
  1439. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1440. */
  1441. public ATObject base_try_catch_using_catch_using_catch_using_(ATClosure tryBlock,
  1442. ATTypeTag filter1, ATClosure hdl1,
  1443. ATTypeTag filter2, ATClosure hdl2,
  1444. ATTypeTag filter3, ATClosure hdl3) throws InterpreterException {
  1445. return base_try_using_using_using_(tryBlock, new NATHandler(filter1, hdl1), new NATHandler(filter2, hdl2), new NATHandler(filter3, hdl3));
  1446. }
  1447. /**
  1448. * The <tt>try:catch:using:catch:using:catch:using:finally:</tt> construct.
  1449. *
  1450. * <pre>try: {
  1451. * tryBlock
  1452. * } catch: type using: { |e|
  1453. * replacementCode
  1454. * } catch: type2 using: { |e|
  1455. * replacementCode2
  1456. * } catch: type3 using: { |e|
  1457. * replacementCode3
  1458. * }</pre>
  1459. *
  1460. * 'Syntactic sugar' for three in-line handlers
  1461. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1462. */
  1463. public ATObject base_try_catch_using_catch_using_catch_using_finally_(ATClosure tryBlock,
  1464. ATTypeTag filter1, ATClosure hdl1,
  1465. ATTypeTag filter2, ATClosure hdl2,
  1466. ATTypeTag filter3, ATClosure hdl3,
  1467. ATClosure finallyBlock) throws InterpreterException {
  1468. return base_try_using_using_using_finally_(tryBlock, new NATHandler(filter1, hdl1), new NATHandler(filter2, hdl2), new NATHandler(filter3, hdl3), finallyBlock);
  1469. }
  1470. /**
  1471. * The <tt>handle: type with: { |e| replacementCode }</tt> construct.
  1472. *
  1473. * @return a first-class handler from a filter prototype and some handler code.
  1474. * @see ATHandler for the interface to which a handler object responds.
  1475. */
  1476. public ATObject base_handle_with_(ATTypeTag filter, ATClosure replacementCode) {
  1477. return new NATHandler(filter, replacementCode);
  1478. }
  1479. /**
  1480. * The <tt>raise: exception</tt> construct.
  1481. *
  1482. * Raises an exception which can be caught by dynamically installed try-catch-using blocks.
  1483. * @see #base_try_usingHandlers_(ATClosure, ATTable)
  1484. */
  1485. public ATNil base_raise_(ATObject anExceptionObject) throws InterpreterException {
  1486. throw Evaluator.asNativeException(anExceptionObject);
  1487. }
  1488. /* --------------------
  1489. * -- Unary Operators -
  1490. * -------------------- */
  1491. /**
  1492. * The unary <tt>!</tt> primitive.
  1493. * <pre>!b == b.not()</pre>
  1494. * @param b the boolean to negate.
  1495. * @return the negation of the boolean.
  1496. */
  1497. public ATBoolean base__opnot_(ATBoolean b) throws InterpreterException {
  1498. return b.base_not();
  1499. }
  1500. /**
  1501. * The unary <tt>-</tt> primitive.
  1502. * <pre>-NUM(n) == 0 - n</pre>
  1503. *
  1504. * @param n a number or a fraction to negate.
  1505. */
  1506. public ATNumeric base__opmns_(ATNumeric n) throws InterpreterException {
  1507. return NATNumber.ZERO.base__opmns_(n);
  1508. }
  1509. /**
  1510. * The unary <tt>+</tt> primitive.
  1511. * <pre>+NBR(n) == NBR(n)</pre>
  1512. */
  1513. public ATNumber base__oppls_(ATNumber n) throws InterpreterException {
  1514. return n;
  1515. }
  1516. /* ---------------------------
  1517. * -- Reactive Programming --
  1518. * --------------------------- */
  1519. /**
  1520. * Returns an event source (with height 0 as it is an initial source of events).
  1521. */
  1522. public ATEventSource base_makeEventSource() throws InterpreterException {
  1523. return new NATEventSource(0);
  1524. }
  1525. public ATEventSource base_merge_(ATTable args) throws InterpreterException {
  1526. return NATEventSource.merge(args);
  1527. }
  1528. /**
  1529. * Pairs an event source to a filter object. For every message propagated on the event source, the
  1530. * corresponding method on the filter will be invoked. The result of this invocation can be either
  1531. * a message to be propagated further or nil.
  1532. * <p>
  1533. * The result of this operation is a derived event source which contains filtered or transformed
  1534. * messages, depending on what the filter object does.
  1535. */
  1536. public ATEventSource base_filter_with_(ATEventSource events, ATObject filter) throws InterpreterException {
  1537. return events.meta_transform(filter);
  1538. }
  1539. /**
  1540. * Pairs an event source to a consumer object. For every message propagated on the event source, the
  1541. * corresponding method on the consumer will be invoked. the result of these subsequent messages are
  1542. * used to determine the value of the behavior that is produced in this way.
  1543. * <p>
  1544. * If the consumer implements a method <tt>initialValue</tt>, this method will be used to determine
  1545. * the initial value of the produced behavior. In the absence of such a method, the initial value is
  1546. * <tt>nil</tt>.
  1547. */
  1548. public ATBehavior base_hold_with_(ATEventSource events, ATObject consumer) throws InterpreterException {
  1549. ATObject initialValue = null;
  1550. try {
  1551. initialValue = consumer.meta_invoke(consumer, new NATMethodInvocation(AGSymbol.jAlloc("initialValue"), NATTable.EMPTY, NATTable.EMPTY));
  1552. } catch (XSelectorNotFound e) {
  1553. initialValue = Evaluator.getNil();
  1554. }
  1555. return new NATBehavior(events, initialValue, consumer);
  1556. }
  1557. /**
  1558. * If the argument is a behavior, returns its current value. Otherwise this function returns the
  1559. * object that was passed to it.
  1560. */
  1561. public ATObject base_value_(ATObject possiblyABehavior) throws InterpreterException {
  1562. if(possiblyABehavior.isBehavior()) {
  1563. ATBehavior aBehavior = possiblyABehavior.asBehavior();
  1564. return aBehavior.meta_value();
  1565. } else {
  1566. return possiblyABehavior;
  1567. }
  1568. }
  1569. /* -------------------
  1570. * -- Miscellaneous --
  1571. * ------------------- */
  1572. /**
  1573. * The <tt>read:</tt> metaprogramming construct. Parses the given text string into an
  1574. * abstract syntax tree.
  1575. *
  1576. * Example: <code>read: "x" => `x</code>
  1577. */
  1578. public ATAbstractGrammar base_read_(ATText source) throws InterpreterException {
  1579. return NATParser._INSTANCE_.base_parse(source);
  1580. }
  1581. /**
  1582. * The <tt>eval:in:</tt> metaprogramming construct.
  1583. * Evaluates the given AST in the context of the given object, returning its value.
  1584. *
  1585. * Example: <code>eval: `x in: object: { def x := 1 } => 1</code>
  1586. *
  1587. * This is a "dangerous" operation in the sense that lexical encapsulation of the given
  1588. * object can be violated.
  1589. */
  1590. public ATObject base_eval_in_(ATAbstractGrammar ast, ATObject obj) throws InterpreterException {
  1591. return ast.meta_eval(new NATContext(obj, obj));
  1592. }
  1593. /**
  1594. * The <tt>print:</tt> metaprogramming construct.
  1595. * This construct invokes the object mirror's <tt>print</tt> method.
  1596. *
  1597. * @return a text string being a human-readable representation of the given object.
  1598. */
  1599. public ATText base_print_(ATObject obj) throws InterpreterException {
  1600. return obj.meta_print();
  1601. }
  1602. /**
  1603. * Compare the receiver object to the <tt>root</tt> object.
  1604. * the reason for this custom implementation: during the execution
  1605. * of this method, 'this' should refer to the global lexical scope object (the root),
  1606. * not to the OBJLexicalRoot instance.
  1607. *
  1608. * When invoking one of these methods lexically, the receiver is always 'root'
  1609. * For example, <code>==(obj)</code> is equivalent to <code>root == obj</code> (or "root.==(obj)")
  1610. */
  1611. public ATBoolean base__opeql__opeql_(ATObject comparand) throws InterpreterException {
  1612. return Evaluator.getGlobalLexicalScope().base__opeql__opeql_(comparand);
  1613. }
  1614. /**
  1615. * Instantiate the <tt>root</tt> object. I.e. <code>new()</code> is equivalent
  1616. * to <tt>root.new()</tt>.
  1617. */
  1618. /*public ATObject base_new(ATObject[] initargs) throws InterpreterException {
  1619. // root.new(@initargs)
  1620. ATObject root = Evaluator.getGlobalLexicalScope();
  1621. return root.meta_invoke(root,NATNil._NEW_NAME_,NATTable.atValue(initargs));
  1622. }*/
  1623. /**
  1624. * After deserialization, ensure that the lexical root remains unique.
  1625. */
  1626. public ATObject meta_resolve() throws InterpreterException {
  1627. return OBJLexicalRoot._INSTANCE_;
  1628. }
  1629. public NATText meta_print() throws InterpreterException {
  1630. return NATText.atValue("lexroot");
  1631. }
  1632. }