/interpreter/tags/at2dist110511/test/edu/vub/at/objects/natives/grammar/TestEval.java

http://ambienttalk.googlecode.com/ · Java · 321 lines · 238 code · 55 blank · 28 comment · 0 complexity · b8a07ac43c7354220718fd54fa509395 MD5 · raw file

  1. package edu.vub.at.objects.natives.grammar;
  2. import edu.vub.at.AmbientTalkTest;
  3. import edu.vub.at.actors.ATAsyncMessage;
  4. import edu.vub.at.eval.Evaluator;
  5. import edu.vub.at.exceptions.InterpreterException;
  6. import edu.vub.at.exceptions.XSelectorNotFound;
  7. import edu.vub.at.exceptions.XUndefinedSlot;
  8. import edu.vub.at.objects.ATAbstractGrammar;
  9. import edu.vub.at.objects.ATClosure;
  10. import edu.vub.at.objects.ATContext;
  11. import edu.vub.at.objects.ATMessage;
  12. import edu.vub.at.objects.ATMethod;
  13. import edu.vub.at.objects.ATMethodInvocation;
  14. import edu.vub.at.objects.ATObject;
  15. import edu.vub.at.objects.ATTable;
  16. import edu.vub.at.objects.grammar.ATSymbol;
  17. import edu.vub.at.objects.natives.NATClosure;
  18. import edu.vub.at.objects.natives.NATMethod;
  19. import edu.vub.at.objects.natives.NATNumber;
  20. import edu.vub.at.objects.natives.NATObject;
  21. import edu.vub.at.objects.natives.NATTable;
  22. import edu.vub.at.objects.natives.NATText;
  23. /**
  24. * Tests the ATObject.meta_eval(ATContext) method for different kinds of abstract grammar elements.
  25. */
  26. public class TestEval extends AmbientTalkTest {
  27. public static void main(String[] args) {
  28. junit.swingui.TestRunner.run(TestEval.class);
  29. }
  30. private final NATNumber atThree_ = NATNumber.atValue(3);
  31. private final AGSymbol atX_ = AGSymbol.alloc(NATText.atValue("x"));
  32. private final AGSymbol atY_ = AGSymbol.alloc(NATText.atValue("y"));
  33. private final AGSymbol atZ_ = AGSymbol.alloc(NATText.atValue("z"));
  34. private final AGSymbol atM_ = AGSymbol.alloc(NATText.atValue("m"));
  35. private final AGSymbol atFooBar_ = AGSymbol.alloc(NATText.atValue("foo:bar:"));
  36. // statements
  37. public void testBegin() {
  38. evalAndCompareTo("1; 2; 3", atThree_);
  39. evalAndCompareTo("3", atThree_);
  40. }
  41. // definitions
  42. public void testDefField() throws InterpreterException {
  43. evalAndCompareTo("def x := 3", atThree_);
  44. assertEquals(atThree_, ctx_.base_lexicalScope().impl_call(atX_, NATTable.EMPTY));
  45. }
  46. public void testDefFunction() throws InterpreterException {
  47. evalAndCompareTo("def x() { 3 }", "<closure:x>");
  48. try {
  49. ATClosure clo = ctx_.base_lexicalScope().impl_lookup(atX_).asClosure();
  50. assertEquals(atX_, clo.base_method().base_name());
  51. } catch(XSelectorNotFound e) {
  52. fail("broken definition:"+e.getMessage());
  53. }
  54. }
  55. public void testDefTable() throws InterpreterException {
  56. evalAndCompareTo("def x[3] { 1; 2; 3 }", "[3, 3, 3]");
  57. try {
  58. ATObject tab = ctx_.base_lexicalScope().impl_call(atX_, NATTable.EMPTY);
  59. assertEquals(atThree_, tab.asTable().base_length());
  60. assertEquals(atThree_, tab.asTable().base_at(NATNumber.ONE));
  61. } catch(XSelectorNotFound e) {
  62. fail("broken definition:"+e.getMessage());
  63. }
  64. }
  65. public void testDefExternalMethod() throws InterpreterException {
  66. ATObject rcvr = new NATObject();
  67. AGSymbol rcvnam = AGSymbol.jAlloc("o");
  68. ctx_.base_lexicalScope().meta_defineField(rcvnam, rcvr);
  69. evalAndCompareTo("def o.x() { self }", "<closure:x>");
  70. try {
  71. ATClosure clo = rcvr.impl_lookup(atX_).asClosure();
  72. assertEquals(atX_, clo.base_method().base_name());
  73. assertEquals(rcvr, rcvr.impl_invoke(rcvr, atX_, NATTable.EMPTY));
  74. } catch(XSelectorNotFound e) {
  75. fail("broken external method definition:"+e.getMessage());
  76. }
  77. }
  78. public void testDefExternalField() throws InterpreterException {
  79. ATObject rcvr = new NATObject();
  80. AGSymbol rcvnam = AGSymbol.jAlloc("o2");
  81. ctx_.base_lexicalScope().meta_defineField(rcvnam, rcvr);
  82. evalAndCompareTo("def o2.x := 3", atThree_);
  83. try {
  84. assertEquals(atThree_, rcvr.impl_invokeAccessor(rcvr, atX_, NATTable.EMPTY));
  85. } catch(XUndefinedSlot e) {
  86. fail("broken external field definition:"+e.getMessage());
  87. }
  88. }
  89. // assignments
  90. public void testAssignVariable() throws InterpreterException {
  91. // def x := nil
  92. ctx_.base_lexicalScope().meta_defineField(atX_, Evaluator.getNil());
  93. evalAndCompareTo("x := 3", atThree_);
  94. assertEquals(atThree_, ctx_.base_lexicalScope().impl_call(atX_, NATTable.EMPTY));
  95. }
  96. public void testAssignTable() throws InterpreterException {
  97. // def x[2] { nil }
  98. ATTable table = NATTable.atValue(new ATObject[] { Evaluator.getNil(), Evaluator.getNil() });
  99. ctx_.base_lexicalScope().meta_defineField(atX_, table);
  100. evalAndCompareTo("x[1] := 3", atThree_);
  101. assertEquals(atThree_, table.base_at(NATNumber.ONE));
  102. }
  103. public void testAssignField() throws InterpreterException {
  104. // def x := object: { def y := 0 }
  105. ATObject x = new NATObject(ctx_.base_lexicalScope());
  106. x.meta_defineField(atY_, NATNumber.ZERO);
  107. ctx_.base_lexicalScope().meta_defineField(atX_, x);
  108. evalAndCompareTo("x.y := 3", atThree_);
  109. assertEquals(atThree_, x.impl_invokeAccessor(x, atY_, NATTable.EMPTY));
  110. }
  111. public void testMultiAssignment() throws InterpreterException {
  112. // def x := 1; def y := 3
  113. ctx_.base_lexicalScope().meta_defineField(atX_, NATNumber.ONE);
  114. ctx_.base_lexicalScope().meta_defineField(atY_, atThree_);
  115. evalAndCompareTo("[x, y] := [ y, x ]", "[3, 1]");
  116. assertEquals(atThree_, ctx_.base_lexicalScope().impl_call(atX_, NATTable.EMPTY));
  117. assertEquals(NATNumber.ONE, ctx_.base_lexicalScope().impl_call(atY_, NATTable.EMPTY));
  118. }
  119. // expressions
  120. public void testSymbolReference() throws InterpreterException {
  121. // def x := 3
  122. ctx_.base_lexicalScope().meta_defineField(atX_, atThree_);
  123. evalAndCompareTo("x", atThree_);
  124. }
  125. public void testTabulation() throws InterpreterException {
  126. // def x := [3,1]
  127. ATTable table = NATTable.atValue(new ATObject[] { atThree_, NATNumber.ONE });
  128. ctx_.base_lexicalScope().meta_defineField(atX_, table);
  129. evalAndCompareTo("x[1]", atThree_);
  130. evalAndCompareTo("x[2]", NATNumber.ONE);
  131. }
  132. public void testClosureLiteral() throws InterpreterException {
  133. ATClosure clo = evalAndReturn("{| x, y | 3 }").asClosure();
  134. ATSymbol nam = clo.base_method().base_name();
  135. ATTable arg = clo.base_method().base_parameters();
  136. ATAbstractGrammar bdy = clo.base_method().base_bodyExpression();
  137. ATContext ctx = clo.base_context();
  138. assertEquals(AGSymbol.alloc(NATText.atValue("lambda")), nam);
  139. assertEquals(atX_, arg.base_at(NATNumber.ONE));
  140. assertEquals(atY_, arg.base_at(NATNumber.atValue(2)));
  141. assertEquals(atThree_, bdy.asBegin().base_statements().base_at(NATNumber.ONE));
  142. assertEquals(ctx_, ctx);
  143. }
  144. public void testSelfReference() throws InterpreterException {
  145. evalAndCompareTo("self", ctx_.base_receiver());
  146. }
  147. public void testSuperReference() throws InterpreterException {
  148. assertEquals(ctx_.base_lexicalScope().base_super(), evalAndReturn("super"));
  149. }
  150. public void testSelection() throws InterpreterException {
  151. // def x := object: { def y() { 3 } }
  152. NATObject x = new NATObject(ctx_.base_receiver());
  153. NATMethod y = new NATMethod(atY_, NATTable.EMPTY, new AGBegin(NATTable.atValue(new ATObject[] { atThree_ })), NATTable.EMPTY);
  154. x.meta_addMethod(y);
  155. ctx_.base_lexicalScope().meta_defineField(atX_, x);
  156. assertEquals(evalAndReturn("x.&y").asClosure().base_method(), y);
  157. }
  158. public void testFirstClassMessage() throws InterpreterException {
  159. ATMessage methInv = evalAndReturn(".m(3)").asMessage();
  160. assertEquals(atM_, methInv.base_selector());
  161. assertEquals(atThree_, methInv.base_arguments().base_at(NATNumber.ONE));
  162. assertTrue(methInv instanceof ATMethodInvocation);
  163. }
  164. public void testFirstClassAsyncMessage() throws Exception {
  165. ATMessage asyncMsg = evalAndReturn("<-m(3)").asMessage();
  166. assertEquals(atM_, asyncMsg.base_selector());
  167. assertEquals(atThree_, asyncMsg.base_arguments().base_at(NATNumber.ONE));
  168. assertTrue(asyncMsg instanceof ATAsyncMessage);
  169. // following is removed because async msges no longer encapsulate their receiver
  170. // assertEquals(OBJNil._INSTANCE_, ((ATAsyncMessage) asyncMsg).base_receiver());
  171. }
  172. public void testMethodApplication() throws InterpreterException {
  173. // def x := 3
  174. ctx_.base_lexicalScope().meta_defineField(atX_, atThree_);
  175. // def identity(x) { x }
  176. ATSymbol identityS = AGSymbol.alloc(NATText.atValue("identity"));
  177. ATTable pars = NATTable.atValue(new ATObject[] { atX_ });
  178. NATMethod identity = new NATMethod(identityS, pars, new AGBegin(NATTable.atValue(new ATObject[] { atX_ })), NATTable.EMPTY);
  179. ctx_.base_lexicalScope().meta_addMethod(identity);
  180. evalAndCompareTo("identity(1)", NATNumber.ONE);
  181. }
  182. public void testClosureApplication() throws InterpreterException {
  183. // def x := 3
  184. ctx_.base_lexicalScope().meta_defineField(atX_, atThree_);
  185. // def identity := { | x | x }
  186. ATSymbol identityS = AGSymbol.alloc(NATText.atValue("identity"));
  187. ATTable pars = NATTable.atValue(new ATObject[] { atX_ });
  188. NATClosure identity = new NATClosure(new NATMethod(identityS, pars, new AGBegin(NATTable.atValue(new ATObject[] { atX_ })), NATTable.EMPTY), ctx_);
  189. ctx_.base_lexicalScope().meta_defineField(identityS, identity);
  190. evalAndCompareTo("identity(1)", NATNumber.ONE);
  191. }
  192. public void testMethodInvocation() throws InterpreterException {
  193. // def x := object: { def x := 3; def m(y) { y; x } }
  194. NATObject x = new NATObject(ctx_.base_lexicalScope());
  195. NATMethod m = new NATMethod(atM_, NATTable.atValue(new ATObject[] { atY_ }),
  196. new AGBegin(NATTable.atValue(new ATObject[] { atY_, atX_ })), NATTable.EMPTY);
  197. x.meta_defineField(atX_, atThree_);
  198. x.meta_addMethod(m);
  199. ctx_.base_lexicalScope().meta_defineField(atX_, x);
  200. evalAndCompareTo("x.m(1)", atThree_);
  201. }
  202. public void testDelegation() throws InterpreterException {
  203. // def x := object: { def m() { self.y + 1 } } ; def y := 2
  204. NATObject x = new NATObject(ctx_.base_lexicalScope());
  205. ATMethod m = evalAndReturn("def m() { self.y + 1 }").asClosure().base_method();
  206. x.meta_addMethod(m);
  207. ctx_.base_receiver().meta_defineField(atY_, NATNumber.atValue(2));
  208. ctx_.base_lexicalScope().meta_defineField(atX_, x);
  209. evalAndCompareTo("x^m()", atThree_);
  210. }
  211. public void testQuotation() throws InterpreterException {
  212. evalAndCompareTo("`3", atThree_);
  213. evalAndCompareTo("`x", atX_);
  214. evalAndCompareTo("`(o.x)", "o.x");
  215. evalAndCompareTo("`(o.&x)", "o.&x");
  216. evalAndCompareTo("`{def x := 3}", "def x := 3");
  217. evalAndCompareTo("`{def x := `3}", "def x := `(3)");
  218. evalAndCompareTo("`{def x := #3}", "def x := 3");
  219. evalAndCompareTo("`{def foo(a) { #([1,2,3]) }}", "def foo(a) { [1, 2, 3] }");
  220. evalAndCompareTo("`{def foo(#@(`([a,b,c]))) { #@([1,2,3]) }}", "def foo(a, b, c) { 1; 2; 3 }");
  221. evalAndCompareTo("`{def foo: x bar: #@(`([y,z])) { 1 }}", "def foo:bar:(x, y, z) { 1 }");
  222. }
  223. public void testArgumentSplicing() throws InterpreterException {
  224. evalAndCompareTo("[1, @[2,[3]], [4], @[5], @[], 6]", "[1, 2, [3], [4], 5, 6]");
  225. // def m(x,y,z) { z }
  226. NATMethod m = new NATMethod(atM_, NATTable.atValue(new ATObject[] { atX_, atY_, atZ_ }),
  227. new AGBegin(NATTable.atValue(new ATObject[] { atZ_ })), NATTable.EMPTY);
  228. ctx_.base_receiver().meta_addMethod(m);
  229. evalAndCompareTo("m(1,@[2,3])", "3");
  230. evalAndCompareTo("self.m(1,@[2,3])", "3");
  231. }
  232. public void testVariableArguments() throws InterpreterException {
  233. // def m(x,y,@z) { [x, y, z] }
  234. NATMethod m = new NATMethod(atM_, NATTable.atValue(new ATObject[] { atX_, atY_, new AGSplice(atZ_) }),
  235. new AGBegin(NATTable.atValue(new ATObject[] {
  236. NATTable.atValue(new ATObject[] { atX_, atY_, atZ_ })
  237. })), NATTable.EMPTY);
  238. ctx_.base_receiver().meta_addMethod(m);
  239. evalAndCompareTo("m(1,2,3,4,5)", "[1, 2, [3, 4, 5]]");
  240. evalAndCompareTo("m(1,2,3)", "[1, 2, [3]]");
  241. evalAndCompareTo("m(1,2)", "[1, 2, []]");
  242. evalAndCompareTo("m(1,2,@[3,4,5])", "[1, 2, [3, 4, 5]]");
  243. evalAndCompareTo("m(@[1,2,3])", "[1, 2, [3]]");
  244. }
  245. public void testVariableKeywordArguments() throws InterpreterException {
  246. // def foo:bar:(x,@y) { y }
  247. NATMethod fooBar = new NATMethod(atFooBar_, NATTable.atValue(new ATObject[] { atX_, new AGSplice(atY_) }),
  248. new AGBegin(NATTable.atValue(new ATObject[] { atY_ })), NATTable.EMPTY);
  249. ctx_.base_receiver().meta_addMethod(fooBar);
  250. evalAndCompareTo("foo: 1 bar: 2", "[2]");
  251. evalAndCompareTo("foo: 1 bar: @[2,3]", "[2, 3]");
  252. evalAndCompareTo("foo: 1 bar: @[2]", "[2]");
  253. evalAndCompareTo("foo: 1 bar: @[]", "[]");
  254. }
  255. public void testVariableMultiDefinition() throws InterpreterException {
  256. // def [x, @y ] := [1, 2, 3, @[4, 5]
  257. // => x = 1; y = [2, 3, 4, 5]
  258. evalAndCompareTo("def [x, @y ] := [1, 2, 3, @[4, 5]]", "[1, 2, 3, 4, 5]");
  259. assertEquals(NATNumber.ONE, ctx_.base_lexicalScope().impl_call(atX_, NATTable.EMPTY));
  260. assertEquals("[2, 3, 4, 5]", ctx_.base_lexicalScope().impl_call(atY_, NATTable.EMPTY).meta_print().javaValue);
  261. }
  262. /** test whether applying an empty closure {} yields nil */
  263. public void testEmptyClosureApplication() throws InterpreterException {
  264. evalAndCompareTo("({})()", "nil");
  265. }
  266. }