PageRenderTime 87ms CodeModel.GetById 42ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

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