/interpreter/tags/at2-build270707/test/edu/vub/at/objects/natives/grammar/TestParameterBinding.java

http://ambienttalk.googlecode.com/ · Java · 362 lines · 184 code · 41 blank · 137 comment · 1 complexity · 9f078a76a7b25f3a53cd7e9828edb965 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. */
  28. package edu.vub.at.objects.natives.grammar;
  29. import edu.vub.at.AmbientTalkTest;
  30. import edu.vub.at.exceptions.InterpreterException;
  31. import edu.vub.at.exceptions.XArityMismatch;
  32. import edu.vub.at.exceptions.XIllegalParameter;
  33. import edu.vub.at.objects.ATObject;
  34. import edu.vub.at.objects.grammar.ATSymbol;
  35. import edu.vub.at.objects.natives.NATContext;
  36. import edu.vub.at.objects.natives.NATMethod;
  37. import edu.vub.at.objects.natives.OBJNil;
  38. import edu.vub.at.objects.natives.NATNumber;
  39. import edu.vub.at.objects.natives.NATObject;
  40. import edu.vub.at.objects.natives.NATTable;
  41. /**
  42. * Unit test for parameter binding during e.g. function call.
  43. *
  44. * @author tvcutsem
  45. */
  46. public class TestParameterBinding extends AmbientTalkTest {
  47. private void ensureBound(ATSymbol var, ATObject value) throws InterpreterException {
  48. assertEquals(value, bindScope_.impl_invokeAccessor(bindScope_, var, NATTable.EMPTY));
  49. }
  50. private void ensureBoundToTable(ATSymbol var, ATObject[] expected) throws InterpreterException {
  51. NATTable val = bindScope_.impl_invokeAccessor(bindScope_, var, NATTable.EMPTY).asNativeTable();
  52. ATObject[] values = val.elements_;
  53. assertEquals(expected.length, values.length);
  54. for (int i = 0; i < values.length; i++) {
  55. assertEquals(expected[i], values[i]);
  56. }
  57. }
  58. /**
  59. * Given a name and parameters, returns a method
  60. * def name(parameters) { nil }
  61. */
  62. private NATMethod makeTestMethod(String nam, NATTable pars) {
  63. try {
  64. return new NATMethod(AGSymbol.jAlloc(nam), pars,
  65. new AGBegin(NATTable.atValue(new ATObject[] { OBJNil._INSTANCE_ })));
  66. } catch (InterpreterException e) {
  67. fail("unexpected exception while creating test fixture: " + e.getMessage());
  68. return null;
  69. }
  70. }
  71. private NATContext bindCtx_;
  72. private NATObject bindScope_;
  73. private final AGSymbol at_a = AGSymbol.jAlloc("a");
  74. private final AGSymbol at_b = AGSymbol.jAlloc("b");
  75. private final AGSymbol at_rest = AGSymbol.jAlloc("rest");
  76. private final AGSymbol at_x = AGSymbol.jAlloc("x");
  77. private final AGSymbol at_y = AGSymbol.jAlloc("y");
  78. // TEST FUNCTIONS
  79. // def fun1() { nil }
  80. private NATMethod fun1 = makeTestMethod("fun1", NATTable.EMPTY);
  81. // def fun2(a,b) { nil }
  82. private NATMethod fun2 = makeTestMethod("fun2", NATTable.atValue(new ATObject[] { at_a, at_b }));
  83. // def fun3(a,b,x := 1) { nil }
  84. private NATMethod fun3 = makeTestMethod("fun3",
  85. NATTable.atValue(new ATObject[] { at_a, at_b, new AGAssignVariable(at_x, NATNumber.ONE) }));
  86. // def fun4(a, x:=a, @rest) { nil }
  87. private NATMethod fun4 = makeTestMethod("fun4",
  88. NATTable.atValue(new ATObject[] { at_a, new AGAssignVariable(at_x, at_a), new AGSplice(at_rest) }));
  89. // def fun5(x := self, y := 0) { nil }
  90. private NATMethod fun5 = makeTestMethod("fun5",
  91. NATTable.atValue(new ATObject[] { new AGAssignVariable(at_x, AGSelf._INSTANCE_), new AGAssignVariable(at_y, NATNumber.ZERO) }));
  92. // def fun6(a, @rest) { nil }
  93. private NATMethod fun6 = makeTestMethod("fun6", NATTable.atValue(new ATObject[] { at_a, new AGSplice(at_rest) }));
  94. // def fun7(@rest) { nil }
  95. private NATMethod fun7 = makeTestMethod("fun7", NATTable.atValue(new ATObject[] { new AGSplice(at_rest) }));
  96. public void setUp() throws InterpreterException {
  97. bindScope_ = new NATObject();
  98. bindCtx_ = new NATContext(bindScope_, bindScope_);
  99. }
  100. /**
  101. * Tests parameter binding for 0-arity methods
  102. */
  103. public void testZeroArity() throws InterpreterException {
  104. // fun1()
  105. fun1.base_applyInScope(NATTable.EMPTY, bindCtx_);
  106. // fun1(0) => arity mismatch
  107. try {
  108. fun1.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO }), bindCtx_);
  109. fail("Expected XArityMismatch exception");
  110. } catch(XArityMismatch e) { }
  111. }
  112. /**
  113. * Tests parameter binding for methods with mandatory arguments only.
  114. */
  115. public void testMandatory() throws InterpreterException {
  116. // normal case: fun2(0,1)
  117. fun2.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE }), bindCtx_);
  118. ensureBound(at_a, NATNumber.ZERO);
  119. ensureBound(at_b, NATNumber.ONE);
  120. }
  121. /**
  122. * Tests for too few mandatory arguments
  123. */
  124. public void testTooFewMandatory() throws InterpreterException {
  125. // too few arguments: fun2(0)
  126. try {
  127. fun2.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO }), bindCtx_);
  128. fail("Expected XArityMismatch exception");
  129. } catch(XArityMismatch e) { }
  130. }
  131. /**
  132. * Tests for too many mandatory arguments
  133. */
  134. public void testTooManyMandatory() throws InterpreterException {
  135. // too many arguments: fun2(0,1,2)
  136. try {
  137. fun2.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2) }), bindCtx_);
  138. fail("Expected XArityMismatch exception");
  139. } catch(XArityMismatch e) { }
  140. }
  141. /**
  142. * Tests parameter binding for methods with mandatory arguments and optional arguments.
  143. */
  144. public void testMandatoryAndOptional() throws InterpreterException {
  145. // normal case: fun3(0,1,2)
  146. fun3.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2) }), bindCtx_);
  147. ensureBound(at_a, NATNumber.ZERO);
  148. ensureBound(at_b, NATNumber.ONE);
  149. ensureBound(at_x, NATNumber.atValue(2));
  150. }
  151. /**
  152. * Tests parameter binding for methods with mandatory arguments and an
  153. * optional argument that is not given.
  154. */
  155. public void testMandatoryAndDefaultOptional() throws InterpreterException {
  156. // fun3(0,1) => ensure optional argument x is bound to default 1
  157. fun3.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE }), bindCtx_);
  158. ensureBound(at_a, NATNumber.ZERO);
  159. ensureBound(at_b, NATNumber.ONE);
  160. ensureBound(at_x, NATNumber.ONE);
  161. }
  162. /**
  163. * Tests whether parameter binding fails if given too many optional arguments.
  164. */
  165. public void testMandatoryAndTooManyOptional() throws InterpreterException {
  166. // fun3(0,1,2,3)
  167. try {
  168. fun3.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2), NATNumber.atValue(3) }), bindCtx_);
  169. fail("Expected XArityMismatch exception");
  170. } catch(XArityMismatch e) { }
  171. }
  172. /**
  173. * Tests application with both mandatory, optional and rest arguments
  174. */
  175. public void testMandOptAndRest() throws InterpreterException {
  176. // fun4(0,1,2,3)
  177. fun4.base_applyInScope(NATTable.atValue(new ATObject[] {
  178. NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2), NATNumber.atValue(3) }), bindCtx_);
  179. ensureBound(at_a, NATNumber.ZERO);
  180. ensureBound(at_x, NATNumber.ONE);
  181. ensureBoundToTable(at_rest, new ATObject[] { NATNumber.atValue(2), NATNumber.atValue(3) });
  182. }
  183. /**
  184. * Tests application with mandatory and optional arguments.
  185. * The rest arguments should be []
  186. */
  187. public void testMandOptAndNoRest() throws InterpreterException {
  188. // fun4(0,1)
  189. fun4.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE }), bindCtx_);
  190. ensureBound(at_a, NATNumber.ZERO);
  191. ensureBound(at_x, NATNumber.ONE);
  192. ensureBound(at_rest, NATTable.EMPTY);
  193. }
  194. /**
  195. * Tests application with mandatory arguments.
  196. * The optional argument should be initialized to its default expression.
  197. * Note that this default expression also tests for let*-like behaviour!
  198. * The rest arguments should be []
  199. */
  200. public void testMandNoOptAndNoRest() throws InterpreterException {
  201. // fun4(3)
  202. fun4.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.atValue(3) }), bindCtx_);
  203. ensureBound(at_a, NATNumber.atValue(3));
  204. ensureBound(at_x, NATNumber.atValue(3));
  205. ensureBound(at_rest, NATTable.EMPTY);
  206. }
  207. /**
  208. * Tests application with only optional arguments, all of which are given at call time.
  209. */
  210. public void testOnlyOptionalArguments() throws InterpreterException {
  211. // fun5(0,1)
  212. fun5.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE }), bindCtx_);
  213. ensureBound(at_x, NATNumber.ZERO);
  214. ensureBound(at_y, NATNumber.ONE);
  215. }
  216. /**
  217. * Tests application with only optional arguments, only one of which is given at call time.
  218. */
  219. public void testOnlyOptArgsWithOneFilledIn() throws InterpreterException {
  220. // fun5(0)
  221. fun5.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO }), bindCtx_);
  222. ensureBound(at_x, NATNumber.ZERO);
  223. ensureBound(at_y, NATNumber.ZERO);
  224. }
  225. /**
  226. * Tests application with only optional arguments, none of which are given at call time.
  227. */
  228. public void testOnlyOptArgsWithNoneFilledIn() throws InterpreterException {
  229. // fun5()
  230. fun5.base_applyInScope(NATTable.EMPTY, bindCtx_);
  231. ensureBound(at_x, bindScope_);
  232. ensureBound(at_y, NATNumber.ZERO);
  233. }
  234. /**
  235. * Tests application with one mandatory argument and zero rest arguments.
  236. */
  237. public void testOneMandatoryAndNoRestArgs() throws InterpreterException {
  238. // fun6(0)
  239. fun6.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO }), bindCtx_);
  240. ensureBound(at_a, NATNumber.ZERO);
  241. ensureBound(at_rest, NATTable.EMPTY);
  242. }
  243. /**
  244. * Tests application with one mandatory argument and two rest arguments.
  245. */
  246. public void testOneMandatoryAndTwoRestArgs() throws InterpreterException {
  247. // fun6(0,1,2)
  248. fun6.base_applyInScope(NATTable.atValue(
  249. new ATObject[] { NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2) }), bindCtx_);
  250. ensureBound(at_a, NATNumber.ZERO);
  251. ensureBoundToTable(at_rest, new ATObject[] { NATNumber.ONE, NATNumber.atValue(2)});
  252. }
  253. /**
  254. * Tests only rest arguments, with none given.
  255. */
  256. public void testZeroRestArgs() throws InterpreterException {
  257. // fun7()
  258. fun7.base_applyInScope(NATTable.EMPTY, bindCtx_);
  259. ensureBound(at_rest, NATTable.EMPTY);
  260. }
  261. /**
  262. * Tests only rest arguments, with one given.
  263. */
  264. public void testOneRestArg() throws InterpreterException {
  265. // fun7(0)
  266. fun7.base_applyInScope(NATTable.atValue(new ATObject[] { NATNumber.ZERO }), bindCtx_);
  267. ensureBoundToTable(at_rest, new ATObject[] { NATNumber.ZERO });
  268. }
  269. /**
  270. * Tests whether mandatory arguments specified after optional arguments
  271. * results in a proper XIllegalParameter exception.
  272. */
  273. public void testIllegalMandatoryAfterOptional() throws InterpreterException {
  274. // def fun8(x:=0, a) { nil }
  275. try {
  276. new NATMethod(AGSymbol.jAlloc("fun8"),
  277. NATTable.atValue(new ATObject[] { new AGAssignVariable(at_x, NATNumber.ZERO), at_a }),
  278. new AGBegin(NATTable.atValue(new ATObject[] { OBJNil._INSTANCE_ })));
  279. fail("Expected XIllegalParameter exception");
  280. } catch(XIllegalParameter e) { }
  281. }
  282. /**
  283. * Tests whether mandatory arguments specified after the rest parameter
  284. * results in a proper XIllegalParameter exception.
  285. */
  286. public void testIllegalMandatoryAfterRest() throws InterpreterException {
  287. // def fun8(x:=0, a) { nil }
  288. try {
  289. new NATMethod(AGSymbol.jAlloc("fun9"),
  290. NATTable.atValue(new ATObject[] { new AGSplice(at_rest), at_a }),
  291. new AGBegin(NATTable.atValue(new ATObject[] { OBJNil._INSTANCE_ })));
  292. fail("Expected XIllegalParameter exception");
  293. } catch(XIllegalParameter e) { }
  294. }
  295. /**
  296. * Tests whether optional arguments specified after the rest parameter
  297. * results in a proper XIllegalParameter exception.
  298. */
  299. public void testIllegalOptionalAfterRest() throws InterpreterException {
  300. // def fun8(x:=0, a) { nil }
  301. try {
  302. new NATMethod(AGSymbol.jAlloc("fun10"),
  303. NATTable.atValue(new ATObject[] { new AGSplice(at_rest), new AGAssignVariable(at_x, NATNumber.ZERO) }),
  304. new AGBegin(NATTable.atValue(new ATObject[] { OBJNil._INSTANCE_ })));
  305. fail("Expected XIllegalParameter exception");
  306. } catch(XIllegalParameter e) { }
  307. }
  308. /**
  309. * Tests whether optional and rest parameters also work using multiple-definition
  310. */
  311. public void testMultiAssignmentWithOptionalAndRestParameters() throws InterpreterException {
  312. // def [a,x:=a,@rest] := [0,1,2]
  313. AGMultiDefinition multiDef = new AGMultiDefinition(
  314. fun4.base_parameters(),
  315. NATTable.atValue(new ATObject[] { NATNumber.ZERO, NATNumber.ONE, NATNumber.atValue(2) }));
  316. multiDef.meta_eval(bindCtx_);
  317. ensureBound(at_a, NATNumber.ZERO);
  318. ensureBound(at_x, NATNumber.ONE);
  319. ensureBoundToTable(at_rest, new ATObject[] { NATNumber.atValue(2)});
  320. }
  321. }