PageRenderTime 25ms CodeModel.GetById 10ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 1ms

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