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

http://ambienttalk.googlecode.com/ · Java · 642 lines · 361 code · 105 blank · 176 comment · 7 complexity · ecd24aedb027c23244a3ebf240423608 MD5 · raw file

  1. /**
  2. * AmbientTalk/2 Project
  3. * NATNil.java created on Jul 13, 2006 at 9:38:51 PM
  4. * (c) Programming Technology Lab, 2006 - 2007
  5. * Authors: Tom Van Cutsem & Stijn Mostinckx
  6. *
  7. * Permission is hereby granted, free of charge, to any person
  8. * obtaining a copy of this software and associated documentation
  9. * files (the "Software"), to deal in the Software without
  10. * restriction, including without limitation the rights to use,
  11. * copy, modify, merge, publish, distribute, sublicense, and/or
  12. * sell copies of the Software, and to permit persons to whom the
  13. * Software is furnished to do so, subject to the following
  14. * conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be
  17. * included in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  20. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  21. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  23. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  24. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  26. * OTHER DEALINGS IN THE SOFTWARE.
  27. */
  28. package edu.vub.at.objects.natives;
  29. import edu.vub.at.actors.ATActorMirror;
  30. import edu.vub.at.actors.ATAsyncMessage;
  31. import edu.vub.at.actors.ATFarReference;
  32. import edu.vub.at.actors.natives.NATFarReference;
  33. import edu.vub.at.actors.net.SerializationException;
  34. import edu.vub.at.eval.Evaluator;
  35. import edu.vub.at.exceptions.InterpreterException;
  36. import edu.vub.at.exceptions.XIllegalOperation;
  37. import edu.vub.at.exceptions.XSelectorNotFound;
  38. import edu.vub.at.exceptions.XTypeMismatch;
  39. import edu.vub.at.exceptions.XUnassignableField;
  40. import edu.vub.at.exceptions.XUndefinedField;
  41. import edu.vub.at.exceptions.XAmbienttalk;
  42. import edu.vub.at.objects.ATBoolean;
  43. import edu.vub.at.objects.ATClosure;
  44. import edu.vub.at.objects.ATContext;
  45. import edu.vub.at.objects.ATField;
  46. import edu.vub.at.objects.ATHandler;
  47. import edu.vub.at.objects.ATMessage;
  48. import edu.vub.at.objects.ATMethod;
  49. import edu.vub.at.objects.ATNil;
  50. import edu.vub.at.objects.ATNumber;
  51. import edu.vub.at.objects.ATObject;
  52. import edu.vub.at.objects.ATStripe;
  53. import edu.vub.at.objects.ATTable;
  54. import edu.vub.at.objects.grammar.ATAssignVariable;
  55. import edu.vub.at.objects.grammar.ATBegin;
  56. import edu.vub.at.objects.grammar.ATDefinition;
  57. import edu.vub.at.objects.grammar.ATExpression;
  58. import edu.vub.at.objects.grammar.ATMessageCreation;
  59. import edu.vub.at.objects.grammar.ATSplice;
  60. import edu.vub.at.objects.grammar.ATStatement;
  61. import edu.vub.at.objects.grammar.ATSymbol;
  62. import edu.vub.at.objects.grammar.ATUnquoteSplice;
  63. import edu.vub.at.objects.mirrors.NATMirage;
  64. import edu.vub.at.objects.mirrors.Reflection;
  65. import edu.vub.at.objects.symbiosis.JavaClass;
  66. import edu.vub.at.objects.symbiosis.JavaObject;
  67. import edu.vub.at.objects.symbiosis.SymbioticATObjectMarker;
  68. import edu.vub.at.util.logging.Logging;
  69. import java.io.InvalidObjectException;
  70. import java.io.ObjectStreamException;
  71. import java.io.Serializable;
  72. /**
  73. * NATNil implements default semantics for all test and conversion methods.
  74. *
  75. * @author smostinc
  76. */
  77. public class NATNil implements ATNil, Serializable {
  78. protected NATNil() {};
  79. public final static NATNil _INSTANCE_ = new NATNil();
  80. /* ------------------------------
  81. * -- Message Sending Protocol --
  82. * ------------------------------ */
  83. /**
  84. * Asynchronous messages ( o<-m( args )) sent in the context of an object o (i.e.
  85. * sent in a method or closure where the self pseudovariable is bound to o) are
  86. * delegated to the base-level send method of the actor in which the object o is
  87. * contained.
  88. */
  89. public ATObject meta_send(ATAsyncMessage message) throws InterpreterException {
  90. return OBJLexicalRoot._INSTANCE_.base_getActor().base_send(message);
  91. }
  92. /**
  93. * By default, when an object receives an incoming asynchronous message, it tells
  94. * the message to process itself. The message's default behaviour is to subsequently
  95. * invoke the method corresponding to the message's selector on this object.
  96. */
  97. public ATObject meta_receive(ATAsyncMessage message) throws InterpreterException {
  98. return message.base_process(this);
  99. }
  100. /**
  101. * The default behaviour of 'invoke' for primitive non-object ambienttalk language values is
  102. * to check whether the requested functionality is provided by a native Java method
  103. * with the same selector, but prefixed with <tt>base_</tt>.
  104. *
  105. * Because an explicit AmbientTalk method invocation must be converted into an implicit
  106. * Java method invocation, the invocation must be deified ('upped'). The result of the
  107. * upped invocation is a Java object, which must subsequently be 'downed' again.
  108. *
  109. * If no method to invoke is found, doesNotUnderstand is invoked which should
  110. * return a closure to be invoked with the appropriate arguments.
  111. */
  112. public ATObject meta_invoke(ATObject receiver, ATSymbol atSelector, ATTable arguments) throws InterpreterException {
  113. try {
  114. String jSelector = Reflection.upBaseLevelSelector(atSelector);
  115. return Reflection.upInvocation(this /*receiver*/, jSelector, atSelector, arguments);
  116. } catch (XSelectorNotFound e) {
  117. e.catchOnlyIfSelectorEquals(atSelector);
  118. return receiver.meta_doesNotUnderstand(atSelector).asClosure().base_apply(arguments);
  119. }
  120. }
  121. /**
  122. * An ambienttalk language value can respond to a message if it implements
  123. * a native Java method corresponding to the selector prefixed by 'base_'.
  124. */
  125. public ATBoolean meta_respondsTo(ATSymbol atSelector) throws InterpreterException {
  126. String jSelector = Reflection.upBaseLevelSelector(atSelector);
  127. return NATBoolean.atValue(Reflection.upRespondsTo(this, jSelector));
  128. }
  129. /**
  130. * By default, when a selection is not understood by a primitive object, an error is raised.
  131. */
  132. public ATObject meta_doesNotUnderstand(ATSymbol selector) throws InterpreterException {
  133. throw new XSelectorNotFound(selector, this);
  134. }
  135. /* ------------------------------------------
  136. * -- Slot accessing and mutating protocol --
  137. * ------------------------------------------ */
  138. /**
  139. * It is possible to select a method from any ambienttalk value provided that it
  140. * offers the method in its provided interface. The result is a NativeMethod wrapper
  141. * which encapsulates the reflective Method object as well as the receiver.
  142. *
  143. * There exists a certain ambiguity in field selection on AmbientTalk implementation-level objects.
  144. * When nativeObject.m is evaluated, the corresponding Java class must have a method named either
  145. * base_getM which means m is represented as a readable field, or
  146. * base_m which means m is represented as a method
  147. */
  148. public ATObject meta_select(ATObject receiver, ATSymbol selector) throws InterpreterException {
  149. String jSelector = Reflection.upBaseFieldAccessSelector(selector);
  150. try {
  151. return Reflection.upFieldSelection(this, jSelector, selector);
  152. } catch (XSelectorNotFound e) {
  153. e.catchOnlyIfSelectorEquals(selector);
  154. jSelector = Reflection.upBaseLevelSelector(selector);
  155. try {
  156. return Reflection.upMethodSelection(this, jSelector, selector);
  157. } catch (XSelectorNotFound e2) {
  158. e2.catchOnlyIfSelectorEquals(selector);
  159. return receiver.meta_doesNotUnderstand(selector);
  160. }
  161. }
  162. }
  163. /**
  164. * A lookup can only be issued at the base level by writing <tt>selector</tt> inside the scope
  165. * of a particular object. For primitive language values, this should not happen
  166. * as no AmbientTalk code can be possibly nested within native code. However, using
  167. * meta-programming a primitive object could be installed as the lexical parent of an AmbientTalk object.
  168. *
  169. * One particular case where this method will often be called is when a lookup reaches
  170. * the lexical root, OBJLexicalRoot, which inherits this implementation.
  171. *
  172. * In such cases a lookup is treated exactly like a selection, where the 'original receiver'
  173. * of the selection equals the primitive object.
  174. */
  175. public ATObject meta_lookup(ATSymbol selector) throws InterpreterException {
  176. try {
  177. return this.meta_select(this, selector);
  178. } catch(XSelectorNotFound e) {
  179. // transform selector not found in undefined variable access
  180. throw new XUndefinedField("variable access", selector.base_getText().asNativeText().javaValue);
  181. }
  182. }
  183. public ATNil meta_defineField(ATSymbol name, ATObject value) throws InterpreterException {
  184. throw new XIllegalOperation("Cannot add fields to " + Evaluator.valueNameOf(this.getClass()));
  185. }
  186. /**
  187. * Normally, a variable assignment cannot be performed on a native AmbientTalk object.
  188. * This is because a variable assignment can normally be only raised by performing
  189. * an assignment in the lexical scope of an object. However, using metaprogramming
  190. * a native object could be installed as the lexical parent of an AT object. In such
  191. * cases, variable assignment is treated as field assignment.
  192. *
  193. * One particular case where this method will often be called is when a variable assignment reaches
  194. * the lexical root, OBJLexicalRoot, which inherits this implementation.
  195. */
  196. public ATNil meta_assignVariable(ATSymbol name, ATObject value) throws InterpreterException {
  197. return this.meta_assignField(this, name, value);
  198. }
  199. public ATNil meta_assignField(ATObject receiver, ATSymbol name, ATObject value) throws InterpreterException {
  200. String jSelector = Reflection.upBaseFieldMutationSelector(name);
  201. // try to invoke a native base_setName method
  202. try {
  203. Reflection.upFieldAssignment(receiver, jSelector, name, value);
  204. } catch (XSelectorNotFound e) {
  205. e.catchOnlyIfSelectorEquals(name);
  206. // if such a method does not exist, the field assignment has failed
  207. throw new XUnassignableField(name.base_getText().asNativeText().javaValue);
  208. }
  209. return NATNil._INSTANCE_;
  210. }
  211. /* ------------------------------------
  212. * -- Extension and cloning protocol --
  213. * ------------------------------------ */
  214. public ATObject meta_clone() throws InterpreterException {
  215. throw new XIllegalOperation("Cannot clone a native object of type " + this.getClass().getName());
  216. }
  217. public ATObject meta_newInstance(ATTable initargs) throws InterpreterException {
  218. return Reflection.upInstanceCreation(this, initargs);
  219. }
  220. /* ---------------------------------
  221. * -- Structural Access Protocol --
  222. * --------------------------------- */
  223. public ATNil meta_addField(ATField field) throws InterpreterException {
  224. throw new XIllegalOperation("Cannot add fields to " + Evaluator.valueNameOf(this.getClass()));
  225. }
  226. public ATNil meta_addMethod(ATMethod method) throws InterpreterException {
  227. throw new XIllegalOperation("Cannot add methods to " + Evaluator.valueNameOf(this.getClass()));
  228. }
  229. public ATField meta_grabField(ATSymbol fieldName) throws InterpreterException {
  230. return Reflection.downBaseLevelField(this, fieldName);
  231. }
  232. public ATMethod meta_grabMethod(ATSymbol methodName) throws InterpreterException {
  233. return Reflection.downBaseLevelMethod(this, methodName);
  234. }
  235. public ATTable meta_listFields() throws InterpreterException {
  236. return NATTable.atValue(Reflection.downBaseLevelFields(this));
  237. }
  238. public ATTable meta_listMethods() throws InterpreterException {
  239. return NATTable.atValue(Reflection.downBaseLevelMethods(this));
  240. }
  241. /* ---------------------------------
  242. * -- Abstract Grammar Protocol --
  243. * --------------------------------- */
  244. /**
  245. * All NATObjects which are not Abstract Grammar elements are self-evaluating.
  246. */
  247. public ATObject meta_eval(ATContext ctx) throws InterpreterException {
  248. return this;
  249. }
  250. /**
  251. * Quoting a native object returns itself, except for pure AG elements.
  252. */
  253. public ATObject meta_quote(ATContext ctx) throws InterpreterException {
  254. return this;
  255. }
  256. public NATText meta_print() throws InterpreterException {
  257. return NATText.atValue("nil");
  258. }
  259. /* ------------------------------
  260. * -- ATObject Mirror Fields --
  261. * ------------------------------ */
  262. /**
  263. * Native objects have a SHARES-A parent link to 'nil', by default.
  264. */
  265. public ATBoolean meta_isExtensionOfParent() throws InterpreterException {
  266. return NATBoolean.atValue((NATObject._SHARES_A_));
  267. };
  268. /**
  269. * By default numbers, tables and so on do not have lexical parents,
  270. */
  271. public ATObject meta_getLexicalParent() throws InterpreterException {
  272. return NATNil._INSTANCE_;
  273. }
  274. /* ---------------------------------
  275. * -- Value Conversion Protocol --
  276. * --------------------------------- */
  277. public boolean isClosure() throws InterpreterException {
  278. return false;
  279. }
  280. public boolean isSymbol() throws InterpreterException {
  281. return false;
  282. }
  283. public boolean isBoolean() throws InterpreterException {
  284. return false;
  285. }
  286. public boolean isTable() throws InterpreterException {
  287. return false;
  288. }
  289. public boolean isCallFrame() throws InterpreterException {
  290. return false;
  291. }
  292. public boolean isUnquoteSplice() throws InterpreterException {
  293. return false;
  294. }
  295. public boolean isVariableAssignment() throws InterpreterException {
  296. return false;
  297. }
  298. public boolean isSplice() throws InterpreterException {
  299. return false;
  300. }
  301. public boolean isMethod() throws InterpreterException {
  302. return false;
  303. }
  304. public boolean isMessageCreation() throws InterpreterException {
  305. return false;
  306. }
  307. public boolean isAmbientTalkObject() {
  308. return false;
  309. }
  310. public boolean isJavaObjectUnderSymbiosis() {
  311. return false;
  312. }
  313. public boolean isNativeBoolean() {
  314. return false;
  315. }
  316. public boolean isNativeText() {
  317. return false;
  318. }
  319. public boolean isNativeField() {
  320. return false;
  321. }
  322. public boolean isStripe() throws InterpreterException {
  323. return false;
  324. }
  325. public ATClosure asClosure() throws InterpreterException {
  326. throw new XTypeMismatch(ATClosure.class, this);
  327. }
  328. public ATSymbol asSymbol() throws InterpreterException {
  329. throw new XTypeMismatch(ATSymbol.class, this);
  330. }
  331. public ATTable asTable() throws InterpreterException {
  332. throw new XTypeMismatch(ATTable.class, this);
  333. }
  334. public ATBoolean asBoolean() throws InterpreterException {
  335. throw new XTypeMismatch(ATBoolean.class, this);
  336. }
  337. public ATNumber asNumber() throws InterpreterException {
  338. throw new XTypeMismatch(ATNumber.class, this);
  339. }
  340. public ATMessage asMessage() throws InterpreterException {
  341. throw new XTypeMismatch(ATMessage.class, this);
  342. }
  343. public ATField asField() throws InterpreterException {
  344. throw new XTypeMismatch(ATField.class, this);
  345. }
  346. public ATMethod asMethod() throws InterpreterException {
  347. throw new XTypeMismatch(ATMethod.class, this);
  348. }
  349. public ATHandler asHandler() throws InterpreterException {
  350. throw new XTypeMismatch(ATHandler.class, this);
  351. }
  352. public ATStripe asStripe() throws InterpreterException {
  353. throw new XTypeMismatch(ATStripe.class, this);
  354. }
  355. // Conversions for concurrency and distribution related object
  356. public boolean isFarReference() {
  357. return false;
  358. }
  359. public ATFarReference asFarReference() throws InterpreterException {
  360. throw new XTypeMismatch(ATFarReference.class, this);
  361. }
  362. public ATAsyncMessage asAsyncMessage() throws InterpreterException {
  363. throw new XTypeMismatch(ATAsyncMessage.class, this);
  364. }
  365. public ATActorMirror asActorMirror() throws InterpreterException {
  366. throw new XTypeMismatch(ATActorMirror.class, this);
  367. }
  368. // Conversions for abstract grammar elements
  369. public ATStatement asStatement() throws InterpreterException {
  370. throw new XTypeMismatch(ATStatement.class, this);
  371. }
  372. public ATDefinition asDefinition() throws InterpreterException {
  373. throw new XTypeMismatch(ATDefinition.class, this);
  374. }
  375. public ATExpression asExpression() throws InterpreterException {
  376. throw new XTypeMismatch(ATExpression.class, this);
  377. }
  378. public ATBegin asBegin() throws InterpreterException {
  379. throw new XTypeMismatch(ATBegin.class, this);
  380. }
  381. public ATMessageCreation asMessageCreation() throws InterpreterException {
  382. throw new XTypeMismatch(ATMessageCreation.class, this);
  383. }
  384. public ATUnquoteSplice asUnquoteSplice() throws InterpreterException {
  385. throw new XTypeMismatch(ATUnquoteSplice.class, this);
  386. }
  387. public ATAssignVariable asVariableAssignment() throws InterpreterException {
  388. throw new XTypeMismatch(ATAssignVariable.class, this);
  389. }
  390. public ATSplice asSplice() throws InterpreterException {
  391. throw new XTypeMismatch(ATSplice.class, this);
  392. }
  393. // Conversions for native values
  394. public NATObject asAmbientTalkObject() throws XTypeMismatch {
  395. throw new XTypeMismatch(NATObject.class, this);
  396. }
  397. public NATMirage asMirage() throws XTypeMismatch {
  398. throw new XTypeMismatch(NATMirage.class, this);
  399. }
  400. public NATNumber asNativeNumber() throws XTypeMismatch {
  401. throw new XTypeMismatch(NATNumber.class, this);
  402. }
  403. public NATFraction asNativeFraction() throws XTypeMismatch {
  404. throw new XTypeMismatch(NATFraction.class, this);
  405. }
  406. public NATText asNativeText() throws XTypeMismatch {
  407. throw new XTypeMismatch(NATText.class, this);
  408. }
  409. public NATTable asNativeTable() throws XTypeMismatch {
  410. throw new XTypeMismatch(NATTable.class, this);
  411. }
  412. public NATBoolean asNativeBoolean() throws XTypeMismatch {
  413. throw new XTypeMismatch(NATBoolean.class, this);
  414. }
  415. public NATNumeric asNativeNumeric() throws XTypeMismatch {
  416. throw new XTypeMismatch(NATNumeric.class, this);
  417. }
  418. public NATFarReference asNativeFarReference() throws XTypeMismatch {
  419. throw new XTypeMismatch(NATFarReference.class, this);
  420. }
  421. public JavaObject asJavaObjectUnderSymbiosis() throws XTypeMismatch {
  422. throw new XTypeMismatch(JavaObject.class, this);
  423. }
  424. public JavaClass asJavaClassUnderSymbiosis() throws XTypeMismatch {
  425. throw new XTypeMismatch(JavaClass.class, this);
  426. }
  427. /**
  428. * Only true objects have a dynamic pointer, native objects denote 'nil' to
  429. * be their dynamic parent when asked for it. Note that, for native objects,
  430. * 'super' is a read-only field (i.e. there is no base_setSuper).
  431. */
  432. public ATObject base_getSuper() throws InterpreterException {
  433. return NATNil._INSTANCE_;
  434. };
  435. public String toString() {
  436. return Evaluator.toString(this);
  437. }
  438. /**
  439. * Java method invocations of equals are transformed into
  440. * AmbientTalk '==' method invocations.
  441. */
  442. public boolean equals(Object other) {
  443. try {
  444. if (other instanceof ATObject) {
  445. return this.base__opeql__opeql_((ATObject) other).asNativeBoolean().javaValue;
  446. } else if (other instanceof SymbioticATObjectMarker) {
  447. return this.base__opeql__opeql_(
  448. ((SymbioticATObjectMarker) other)._returnNativeAmbientTalkObject()).asNativeBoolean().javaValue;
  449. }
  450. } catch (InterpreterException e) {
  451. Logging.Actor_LOG.warn("Error during equality testing:", e);
  452. }
  453. return false;
  454. }
  455. /**
  456. * By default, two AmbientTalk objects are equal if they are the
  457. * same object, or one is a proxy for the same object.
  458. */
  459. public ATBoolean base__opeql__opeql_(ATObject other) throws InterpreterException {
  460. // by default, ATObjects use pointer equality
  461. return NATBoolean.atValue(this == other);
  462. }
  463. public ATObject base_new(ATObject[] initargs) throws InterpreterException {
  464. return this.meta_newInstance(NATTable.atValue(initargs));
  465. }
  466. public ATObject base_init(ATObject[] initargs) throws InterpreterException {
  467. return NATNil._INSTANCE_;
  468. }
  469. public ATBoolean meta_isCloneOf(ATObject original) throws InterpreterException {
  470. return NATBoolean.atValue(
  471. this.getClass() == original.getClass());
  472. }
  473. public ATBoolean meta_isRelatedTo(ATObject object) throws InterpreterException {
  474. return this.meta_isCloneOf(object);
  475. }
  476. /* ---------------------------------
  477. * -- Stripe Testing and Querying --
  478. * --------------------------------- */
  479. /**
  480. * Native objects implement the stripe test non-recursively: only the stripes
  481. * returned by meta_getStripes are tested against.
  482. */
  483. public ATBoolean meta_isStripedWith(ATStripe stripe) throws InterpreterException {
  484. ATObject[] stripes = this.meta_getStripes().asNativeTable().elements_;
  485. for (int i = 0; i < stripes.length; i++) {
  486. if (stripes[i].asStripe().base_isSubstripeOf(stripe).asNativeBoolean().javaValue) {
  487. return NATBoolean._TRUE_;
  488. }
  489. }
  490. return NATBoolean._FALSE_;
  491. }
  492. /**
  493. * By default, a native object (and also nil) has no stripes.
  494. */
  495. public ATTable meta_getStripes() throws InterpreterException {
  496. return NATTable.EMPTY;
  497. }
  498. /* -----------------------------
  499. * -- Object Passing protocol --
  500. * ----------------------------- */
  501. /**
  502. * This method allows objects to decide which object should be serialized in their
  503. * stead when they are passed as argument in an asynchronous message send that
  504. * crosses actor boundaries. By default, nil decides that it is safe to serialize
  505. * the object itself. Special objects such as e.g. closures should override this
  506. * method and return a far reference encoding instead.
  507. */
  508. public ATObject meta_pass() throws InterpreterException {
  509. return this;
  510. }
  511. /**
  512. * After deserialization, ensure that nil remains unique.
  513. */
  514. public ATObject meta_resolve() throws InterpreterException {
  515. return NATNil._INSTANCE_;
  516. }
  517. /**
  518. * Delegate the responsibility of serialization to the AT/2 meta-level
  519. */
  520. public Object writeReplace() throws ObjectStreamException {
  521. try {
  522. return this.meta_pass();
  523. } catch(InterpreterException e) {
  524. throw new InvalidObjectException("Failed to pass object " + this + ": " + e.getMessage());
  525. }
  526. }
  527. /**
  528. * Delegate the responsibility of deserialization to the AT/2 meta-level
  529. */
  530. public Object readResolve() throws ObjectStreamException {
  531. try {
  532. return this.meta_resolve();
  533. } catch(InterpreterException e) {
  534. throw new SerializationException(e);
  535. }
  536. }
  537. }