PageRenderTime 98ms CodeModel.GetById 43ms app.highlight 49ms RepoModel.GetById 2ms app.codeStats 0ms

/interpreter/tags/at_build150307/test/edu/vub/at/objects/natives/grammar/TestParameterBinding.java

http://ambienttalk.googlecode.com/
Java | 362 lines | 184 code | 41 blank | 137 comment | 1 complexity | fd8c223b33cd18ceaab1da0d003453e3 MD5 | raw file
  1/**
  2 * AmbientTalk/2 Project
  3 * TestParameterBinding.java created on 26-dec-2006 at 13:43:59
  4 * (c) Programming Technology Lab, 2006 - 2007
  5 * Authors: Tom Van Cutsem & Stijn Mostinckx
  6 * 
  7 * Permission is hereby granted, free of charge, to any person
  8 * obtaining a copy of this software and associated documentation
  9 * files (the "Software"), to deal in the Software without
 10 * restriction, including without limitation the rights to use,
 11 * copy, modify, merge, publish, distribute, sublicense, and/or
 12 * sell copies of the Software, and to permit persons to whom the
 13 * Software is furnished to do so, subject to the following
 14 * conditions:
 15 *
 16 * The above copyright notice and this permission notice shall be
 17 * included in all copies or substantial portions of the Software.
 18 *
 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 26 * OTHER DEALINGS IN THE SOFTWARE.
 27 */
 28package edu.vub.at.objects.natives.grammar;
 29
 30import edu.vub.at.AmbientTalkTest;
 31import edu.vub.at.exceptions.InterpreterException;
 32import edu.vub.at.exceptions.XArityMismatch;
 33import edu.vub.at.exceptions.XIllegalParameter;
 34import edu.vub.at.objects.ATObject;
 35import edu.vub.at.objects.grammar.ATSymbol;
 36import edu.vub.at.objects.natives.NATContext;
 37import edu.vub.at.objects.natives.NATMethod;
 38import edu.vub.at.objects.natives.NATNil;
 39import edu.vub.at.objects.natives.NATNumber;
 40import edu.vub.at.objects.natives.NATObject;
 41import edu.vub.at.objects.natives.NATTable;
 42
 43/**
 44 * Unit test for parameter binding during e.g. function call.
 45 *
 46 * @author tvcutsem
 47 */
 48public class TestParameterBinding extends AmbientTalkTest {
 49
 50	private void ensureBound(ATSymbol var, ATObject value) throws InterpreterException {
 51		assertEquals(value, bindScope_.meta_select(bindScope_, var));
 52	}
 53	
 54	private void ensureBoundToTable(ATSymbol var, ATObject[] expected) throws InterpreterException {
 55		NATTable val = bindScope_.meta_select(bindScope_, var).asNativeTable();
 56		ATObject[] values = val.elements_;
 57		assertEquals(expected.length, values.length);
 58		for (int i = 0; i < values.length; i++) {
 59			assertEquals(expected[i], values[i]);
 60		}
 61	}
 62	
 63	/**
 64	 * Given a name and parameters, returns a method
 65	 * def name(parameters) { nil }
 66	 */
 67	private NATMethod makeTestMethod(String nam, NATTable pars) {
 68		try {
 69			return new NATMethod(AGSymbol.jAlloc(nam), pars,
 70				new AGBegin(NATTable.atValue(new ATObject[] { NATNil._INSTANCE_ })));
 71		} catch (InterpreterException e) {
 72			fail("unexpected exception while creating test fixture: " + e.getMessage());
 73			return null;
 74		}
 75	}
 76	
 77	private NATContext bindCtx_;
 78	private NATObject  bindScope_;
 79	
 80	private final AGSymbol at_a = AGSymbol.jAlloc("a");
 81	private final AGSymbol at_b = AGSymbol.jAlloc("b");
 82	private final AGSymbol at_rest = AGSymbol.jAlloc("rest");
 83	private final AGSymbol at_x = AGSymbol.jAlloc("x");
 84	private final AGSymbol at_y = AGSymbol.jAlloc("y");
 85	
 86	// TEST FUNCTIONS
 87	
 88	// def fun1() { nil }
 89	private NATMethod fun1 = makeTestMethod("fun1", NATTable.EMPTY);
 90
 91	// def fun2(a,b) { nil }
 92	private NATMethod fun2 = makeTestMethod("fun2", NATTable.atValue(new ATObject[] { at_a, at_b }));
 93	
 94	// def fun3(a,b,x := 1) { nil }
 95	private NATMethod fun3 = makeTestMethod("fun3",
 96		NATTable.atValue(new ATObject[] { at_a, at_b, new AGAssignVariable(at_x, NATNumber.ONE) }));
 97	
 98	// def fun4(a, x:=a, @rest) { nil }
 99	private NATMethod fun4 = makeTestMethod("fun4",
100		NATTable.atValue(new ATObject[] { at_a, new AGAssignVariable(at_x, at_a), new AGSplice(at_rest) }));
101	
102	// def fun5(x := self, y := 0) { nil }
103	private NATMethod fun5 = makeTestMethod("fun5",
104		NATTable.atValue(new ATObject[] { new AGAssignVariable(at_x, AGSelf._INSTANCE_), new AGAssignVariable(at_y, NATNumber.ZERO) }));
105
106	// def fun6(a, @rest) { nil }
107	private NATMethod fun6 = makeTestMethod("fun6", NATTable.atValue(new ATObject[] { at_a, new AGSplice(at_rest) }));
108	
109	// def fun7(@rest) { nil }
110	private NATMethod fun7 = makeTestMethod("fun7", NATTable.atValue(new ATObject[] { new AGSplice(at_rest) }));
111
112
113	public void setUp() throws InterpreterException {
114		bindScope_ = new NATObject();
115		bindCtx_ = new NATContext(bindScope_, bindScope_);
116	}
117	
118	/**
119	 * Tests parameter binding for 0-arity methods
120	 */
121	public void testZeroArity() throws InterpreterException {
122		// fun1()
123		fun1.base_applyInScope(NATTable.EMPTY, bindCtx_);
124		
125		// fun1(0) => arity mismatch
126		try {
127			fun1.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO }), bindCtx_);
128			fail("Expected XArityMismatch exception");
129		} catch(XArityMismatch e) { }
130	}
131	
132	/**
133	 * Tests parameter binding for methods with mandatory arguments only.
134	 */
135	public void testMandatory() throws InterpreterException {
136		// normal case: fun2(0,1)
137		fun2.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE }), bindCtx_);
138		ensureBound(at_a, NATNumber.ZERO);
139		ensureBound(at_b, NATNumber.ONE);
140	}
141	
142	/**
143	 * Tests for too few mandatory arguments
144	 */
145	public void testTooFewMandatory() throws InterpreterException {
146		// too few arguments: fun2(0)
147		try {
148			fun2.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO }), bindCtx_);
149			fail("Expected XArityMismatch exception");
150		} catch(XArityMismatch e) { }
151	}
152	
153	/**
154	 * Tests for too many mandatory arguments
155	 */
156	public void testTooManyMandatory() throws InterpreterException {
157		// too many arguments: fun2(0,1,2)
158		try {
159			fun2.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2) }), bindCtx_);
160			fail("Expected XArityMismatch exception");
161		} catch(XArityMismatch e) { }
162	}
163	
164	/**
165	 * Tests parameter binding for methods with mandatory arguments and optional arguments.
166	 */
167	public void testMandatoryAndOptional() throws InterpreterException {
168		// normal case: fun3(0,1,2)
169		fun3.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2) }), bindCtx_);
170		ensureBound(at_a, NATNumber.ZERO);
171		ensureBound(at_b, NATNumber.ONE);
172		ensureBound(at_x, NATNumber.atValue(2));
173	}
174	
175	/**
176	 * Tests parameter binding for methods with mandatory arguments and an
177	 * optional argument that is not given.
178	 */
179	public void testMandatoryAndDefaultOptional() throws InterpreterException {
180		// fun3(0,1) => ensure optional argument x is bound to default 1
181		fun3.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE }), bindCtx_);
182		ensureBound(at_a, NATNumber.ZERO);
183		ensureBound(at_b, NATNumber.ONE);
184		ensureBound(at_x, NATNumber.ONE);
185	}
186	
187	/**
188	 * Tests whether parameter binding fails if given too many optional arguments.
189	 */
190	public void testMandatoryAndTooManyOptional() throws InterpreterException {
191		// fun3(0,1,2,3)
192		try {
193			fun3.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2), NATNumber.atValue(3) }), bindCtx_);
194			fail("Expected XArityMismatch exception");
195		} catch(XArityMismatch e) { }
196	}
197	
198	/**
199	 * Tests application with both mandatory, optional and rest arguments
200	 */
201	public void testMandOptAndRest() throws InterpreterException {
202		// fun4(0,1,2,3)
203		fun4.base_applyInScope(NATTable.atValue(new ATObject[] {
204				NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2), NATNumber.atValue(3) }), bindCtx_);
205		ensureBound(at_a, NATNumber.ZERO);
206		ensureBound(at_x, NATNumber.ONE);
207		ensureBoundToTable(at_rest, new ATObject[] { NATNumber.atValue(2), NATNumber.atValue(3) });
208	}
209	
210	/**
211	 * Tests application with mandatory and optional arguments.
212	 * The rest arguments should be []
213	 */
214	public void testMandOptAndNoRest() throws InterpreterException {
215		// fun4(0,1)
216		fun4.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE }), bindCtx_);
217		ensureBound(at_a, NATNumber.ZERO);
218		ensureBound(at_x, NATNumber.ONE);
219		ensureBound(at_rest, NATTable.EMPTY);
220	}
221	
222	/**
223	 * Tests application with mandatory arguments.
224	 * The optional argument should be initialized to its default expression.
225	 * Note that this default expression also tests for let*-like behaviour!
226	 * The rest arguments should be []
227	 */
228	public void testMandNoOptAndNoRest() throws InterpreterException {
229		// fun4(3)
230		fun4.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.atValue(3) }), bindCtx_);
231		ensureBound(at_a, NATNumber.atValue(3));
232		ensureBound(at_x, NATNumber.atValue(3));
233		ensureBound(at_rest, NATTable.EMPTY);
234	}
235	
236	/**
237	 * Tests application with only optional arguments, all of which are given at call time.
238	 */
239	public void testOnlyOptionalArguments() throws InterpreterException {
240		// fun5(0,1)
241		fun5.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE }), bindCtx_);
242		ensureBound(at_x, NATNumber.ZERO);
243		ensureBound(at_y, NATNumber.ONE);
244	}
245	
246	/**
247	 * Tests application with only optional arguments, only one of which is given at call time.
248	 */
249	public void testOnlyOptArgsWithOneFilledIn() throws InterpreterException {
250		// fun5(0)
251		fun5.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO }), bindCtx_);
252		ensureBound(at_x, NATNumber.ZERO);
253		ensureBound(at_y, NATNumber.ZERO);
254	}
255	
256	/**
257	 * Tests application with only optional arguments, none of which are given at call time.
258	 */
259	public void testOnlyOptArgsWithNoneFilledIn() throws InterpreterException {
260		// fun5()
261		fun5.base_applyInScope(NATTable.EMPTY, bindCtx_);
262		ensureBound(at_x, bindScope_);
263		ensureBound(at_y, NATNumber.ZERO);
264	}
265	
266	/**
267	 * Tests application with one mandatory argument and zero rest arguments.
268	 */
269	public void testOneMandatoryAndNoRestArgs() throws InterpreterException {
270		// fun6(0)
271		fun6.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO }), bindCtx_);
272		ensureBound(at_a, NATNumber.ZERO);
273		ensureBound(at_rest, NATTable.EMPTY);
274	}
275	
276	/**
277	 * Tests application with one mandatory argument and two rest arguments.
278	 */
279	public void testOneMandatoryAndTwoRestArgs() throws InterpreterException {
280		// fun6(0,1,2)
281		fun6.base_applyInScope(NATTable.atValue(
282				new ATObject[] { NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2) }), bindCtx_);
283		ensureBound(at_a, NATNumber.ZERO);
284		ensureBoundToTable(at_rest, new ATObject[] { NATNumber.ONE, NATNumber.atValue(2)});
285	}
286	
287	/**
288	 * Tests only rest arguments, with none given.
289	 */
290	public void testZeroRestArgs() throws InterpreterException {
291		// fun7()
292		fun7.base_applyInScope(NATTable.EMPTY, bindCtx_);
293		ensureBound(at_rest, NATTable.EMPTY);
294	}
295	
296	/**
297	 * Tests only rest arguments, with one given.
298	 */
299	public void testOneRestArg() throws InterpreterException {
300		// fun7(0)
301		fun7.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO }), bindCtx_);
302		ensureBoundToTable(at_rest, new ATObject[] { NATNumber.ZERO });
303	}
304	
305	
306	/**
307	 * Tests whether mandatory arguments specified after optional arguments
308	 * results in a proper XIllegalParameter exception.
309	 */
310	public void testIllegalMandatoryAfterOptional() throws InterpreterException {
311        // def fun8(x:=0, a) { nil }
312		try {
313		    new NATMethod(AGSymbol.jAlloc("fun8"),
314				NATTable.atValue(new ATObject[] { new AGAssignVariable(at_x, NATNumber.ZERO), at_a }),
315				new AGBegin(NATTable.atValue(new ATObject[] { NATNil._INSTANCE_ })));
316		    fail("Expected XIllegalParameter exception");
317		} catch(XIllegalParameter e) { }
318	}
319	
320	/**
321	 * Tests whether mandatory arguments specified after the rest parameter
322	 * results in a proper XIllegalParameter exception.
323	 */
324	public void testIllegalMandatoryAfterRest() throws InterpreterException {
325        // def fun8(x:=0, a) { nil }
326		try {
327		    new NATMethod(AGSymbol.jAlloc("fun9"),
328				NATTable.atValue(new ATObject[] { new AGSplice(at_rest), at_a }),
329				new AGBegin(NATTable.atValue(new ATObject[] { NATNil._INSTANCE_ })));
330		    fail("Expected XIllegalParameter exception");
331		} catch(XIllegalParameter e) { }
332	}
333	
334	/**
335	 * Tests whether optional arguments specified after the rest parameter
336	 * results in a proper XIllegalParameter exception.
337	 */
338	public void testIllegalOptionalAfterRest() throws InterpreterException {
339        // def fun8(x:=0, a) { nil }
340		try {
341		    new NATMethod(AGSymbol.jAlloc("fun10"),
342				NATTable.atValue(new ATObject[] { new AGSplice(at_rest), new AGAssignVariable(at_x, NATNumber.ZERO) }),
343				new AGBegin(NATTable.atValue(new ATObject[] { NATNil._INSTANCE_ })));
344		    fail("Expected XIllegalParameter exception");
345		} catch(XIllegalParameter e) { }
346	}
347	
348	/**
349	 * Tests whether optional and rest parameters also work using multiple-definition
350	 */
351	public void testMultiAssignmentWithOptionalAndRestParameters() throws InterpreterException {
352		// def [a,x:=a,@rest] := [0,1,2]
353		AGMultiDefinition multiDef = new AGMultiDefinition(
354				fun4.base_getParameters(),
355				NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2) }));
356		multiDef.meta_eval(bindCtx_);
357		ensureBound(at_a, NATNumber.ZERO);
358		ensureBound(at_x, NATNumber.ONE);
359		ensureBoundToTable(at_rest, new ATObject[] { NATNumber.atValue(2)});
360	}
361
362}