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

http://ambienttalk.googlecode.com/ · Java · 210 lines · 140 code · 25 blank · 45 comment · 5 complexity · b899b1cd4af747fd7db4367cfe433e8f MD5 · raw file

  1. /**
  2. * AmbientTalk/2 Project
  3. * TestFreeVariableCapturing.java created on 29 jul 2008 at 11:23:00
  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.XIllegalOperation;
  32. import edu.vub.at.exceptions.XSelectorNotFound;
  33. import edu.vub.at.exceptions.XUndefinedSlot;
  34. import edu.vub.at.objects.ATObject;
  35. import edu.vub.at.objects.grammar.ATBegin;
  36. import edu.vub.at.parser.NATParser;
  37. import java.util.Set;
  38. /**
  39. * Tests the algorithm that automatically deduces lexically free variables in a
  40. * piece of source code.
  41. *
  42. * @author tvcutsem
  43. */
  44. public class TestFreeVariableCapturing extends AmbientTalkTest {
  45. private void ensureEmpty(Set variables) {
  46. assertTrue(variables.toString() + " is empty", variables.isEmpty());
  47. }
  48. private void ensurePresent(String name, Set variables) {
  49. assertTrue(name + " present in "+variables, variables.contains(AGSymbol.jAlloc(name)));
  50. assertTrue("no extra vars in "+variables, variables.size() == 1);
  51. }
  52. private void ensurePresent(String name1, String name2, Set variables) {
  53. assertTrue(name1 + " present in "+variables, variables.contains(AGSymbol.jAlloc(name1)));
  54. assertTrue(name2 + " present in "+variables, variables.contains(AGSymbol.jAlloc(name2)));
  55. assertTrue("no extra vars in "+variables, variables.size() == 2);
  56. }
  57. private void ensurePresent(String name1, String name2, String name3, Set variables) {
  58. assertTrue(name1 + " present in "+variables, variables.contains(AGSymbol.jAlloc(name1)));
  59. assertTrue(name2 + " present in "+variables, variables.contains(AGSymbol.jAlloc(name2)));
  60. assertTrue(name3 + " present in "+variables, variables.contains(AGSymbol.jAlloc(name3)));
  61. assertTrue("no extra vars in "+variables, variables.size() == 3);
  62. }
  63. private void ensurePresent(String[] names, Set variables) {
  64. for (int i = 0; i < names.length; i++) {
  65. assertTrue(names[i] + " present in "+variables, variables.contains(AGSymbol.jAlloc(names[i])));
  66. }
  67. assertTrue("no extra vars in "+variables, variables.size() == names.length);
  68. }
  69. private Set freeVarsOf(String text) throws InterpreterException {
  70. return NATParser.parse("TestFreeVariableCapture unit test", text).impl_freeVariables();
  71. }
  72. public Set introducedVarsOf(String definition) throws InterpreterException {
  73. ATBegin begin = NATParser.parse("unit test", definition).asBegin();
  74. ATObject[] stmts = begin.base_statements().asNativeTable().elements_;
  75. return stmts[0].asDefinition().impl_introducedVariables();
  76. }
  77. public void testElementaryExpressions() throws InterpreterException {
  78. ensureEmpty(freeVarsOf("1"));
  79. ensureEmpty(freeVarsOf("\"text\""));
  80. ensureEmpty(freeVarsOf("self"));
  81. ensureEmpty(freeVarsOf("{}"));
  82. ensureEmpty(freeVarsOf("[]"));
  83. ensureEmpty(freeVarsOf(".m(1)"));
  84. }
  85. public void testVariables() throws InterpreterException {
  86. ensurePresent("x", freeVarsOf("x"));
  87. ensurePresent("nil", freeVarsOf("nil"));
  88. ensurePresent("true", freeVarsOf("true"));
  89. ensurePresent("object:", freeVarsOf("object: { }"));
  90. ensurePresent("x", "y", freeVarsOf("{ x; y }"));
  91. ensurePresent("x", "y", freeVarsOf("[1,x,y,2]"));
  92. ensurePresent("x", freeVarsOf("<-m(x)"));
  93. ensurePresent("o","Foo","x", freeVarsOf("o<-m()@Foo(x)"));
  94. ensurePresent("f", freeVarsOf("f(1)"));
  95. ensurePresent("foo:bar:","x", freeVarsOf("foo: 1 bar: x"));
  96. }
  97. public void testCompositeExpressions() throws InterpreterException {
  98. ensurePresent("x", freeVarsOf("x+1"));
  99. ensurePresent("o", "x", freeVarsOf("o.m(x,1)"));
  100. ensurePresent("t", "i", "v", freeVarsOf("t[i+1] := t[i] - v"));
  101. ensurePresent("o", freeVarsOf("import o alias x := y exclude z"));
  102. ensurePresent("x", freeVarsOf("&x"));
  103. ensurePresent("head", "tail", freeVarsOf("[head, @tail]"));
  104. }
  105. public void testFreeVarsOfDefinitions() throws InterpreterException {
  106. ensureEmpty(freeVarsOf("def x := 1"));
  107. ensurePresent("v", freeVarsOf("def t[4] { 1 + v }"));
  108. ensureEmpty(freeVarsOf("{|x,y| x + y }"));
  109. ensurePresent("y", freeVarsOf("{ |x| x + y }"));
  110. ensureEmpty(freeVarsOf("def x := 1; def y[1] { 2 }; def z();"));
  111. ensurePresent("z", freeVarsOf("def x(y) { z + y }"));
  112. ensurePresent("t1","t2", freeVarsOf("def [x,y] := [t1,t2]"));
  113. ensurePresent("x","y","t", freeVarsOf("[x,y] := t"));
  114. ensurePresent("bar", freeVarsOf("deftype foo <: bar"));
  115. ensurePresent("x","y", freeVarsOf("def m(z) @ x { z + y + m() }"));
  116. ensurePresent("o", "y", freeVarsOf("def o.x := y"));
  117. ensurePresent("v", freeVarsOf("def m(x := v) { x }"));
  118. ensureEmpty(freeVarsOf("def f(x) { def g(y) { x + y } }"));
  119. ensurePresent("free", freeVarsOf("def f(x) { x }; def g(y) { f(free) + g(y) }"));
  120. ensurePresent("free", freeVarsOf("def f(x) { def g(y) { {|z| x + g(y) + free + z } } }"));
  121. }
  122. public void testIntroducedVarsOfDefinitions() throws InterpreterException {
  123. ensurePresent("x", introducedVarsOf("def x := 1"));
  124. ensurePresent("y", introducedVarsOf("def y[1] { 2 }"));
  125. ensurePresent("z", introducedVarsOf("def z();"));
  126. ensureEmpty(introducedVarsOf("def o.z();"));
  127. ensureEmpty(introducedVarsOf("def o.x := y"));
  128. ensurePresent("foo", introducedVarsOf("deftype foo"));
  129. ensurePresent("x", "y", introducedVarsOf("def [x,y] := [1,2]"));
  130. }
  131. public void testQuotedFreeVars() throws InterpreterException {
  132. ensureEmpty(freeVarsOf("`x"));
  133. ensurePresent("foo", freeVarsOf("`{ def #(foo)(arg) { arg } }"));
  134. ensurePresent("y", freeVarsOf("`(x + #(y + 1))"));
  135. ensurePresent("t", freeVarsOf("`(x + #@t)"));
  136. ensurePresent("msg", freeVarsOf("`<-#msg(1)"));
  137. ensurePresent("msg", freeVarsOf("`(o.#msg(1))"));
  138. }
  139. public void testIsolateWithAutomaticLexicalScope() throws InterpreterException {
  140. evalAndCompareTo("def x := 42; def i := isolate: { def m() { x } }; i.m()", "42");
  141. // check whether explicit overriding still works
  142. evalAndTestException("def x2 := 42; def y := 0; def i2 := isolate: { |y| def m() { x2 } }; i2.m()", XUndefinedSlot.class);
  143. // super should never be automatically imported
  144. evalAndCompareTo("def outer := 4; def obj := isolate: { def m() { outer }; super }; obj.m()", "4");
  145. // variables bound to methods are not automatically imported
  146. evalAndTestException("def f(); (isolate: { def m() { f() } }).m()", XUndefinedSlot.class);
  147. // but variables bound to closures are
  148. evalAndCompareTo("def g(); def gclo := &g; (isolate: { def m() { gclo() } }).m()", "nil");
  149. // global variables and functions should be automatically removed
  150. ensurePresent("isolate:", "!", "false", freeVarsOf("isolate: { !false }"));
  151. evalAndCompareTo("(isolate: { def myNot(b) { !b } }).myNot(true)","false");
  152. // automatically imported free variables are 'private' to the isolate
  153. // and thus not publicly accessible
  154. evalAndTestException("def outer2 := 42; def i3 := isolate: { def m() { outer2 } }; i3.outer2", XSelectorNotFound.class);
  155. evalAndCompareTo("i3.m()", "42");
  156. }
  157. public void testActorWithAutomaticLexicalScope() throws InterpreterException {
  158. evalAndCompareTo("def lex := 0; def a := actor: { lex }; nil", "nil");
  159. // global variables and functions should be automatically removed
  160. evalAndCompareTo("(actor: { def myNot(b) { !b } })<-myNot(true)","nil");
  161. }
  162. /**
  163. * Following a bug in the free variable deduction algorithm...
  164. * The variable 'focus' was wrongly flagged as a free variable of the below code snippet.
  165. */
  166. public void testIsolateComplexExample() throws InterpreterException {
  167. Set fv = freeVarsOf("def focussed := false;" +
  168. "def handleMouseClicked(event) {" +
  169. " def hand := event.source;" +
  170. " def currentFocused := hand.focus;" +
  171. " if: (nil.!=(currentFocused).and:({ currentFocused.!=(self) })) then: {" +
  172. " currentFocused.focussed := false" +
  173. " };" +
  174. " if: self.focussed then: {" +
  175. " self.focussed := false;" +
  176. " hand.focus := nil" +
  177. " } else: {" +
  178. " self.focussed := true;" +
  179. " hand.focus := self" +
  180. " }" +
  181. "}");
  182. assertFalse(fv.contains(AGSymbol.jAlloc("focus")));
  183. ensurePresent(new String[] { "nil", "if:then:else:", "true", "if:then:", "false" }, fv);
  184. };
  185. }