package magic.compiler;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.junit.Test;

import magic.ast.Constant;
import magic.ast.Node;
import magic.ast.Lambda;
import magic.ast.Lookup;
import magic.compiler.Analyser;
import magic.compiler.Reader;
import magic.data.PersistentList;
import magic.data.Tuple;
import magic.lang.Context;

public class TestAnalyse {

	@SuppressWarnings("unchecked")
	public <T> Node<T> analyse(String t) {
		return (Node<T>) Analyser.analyse(Reader.read(t));
	}
	
	@Test 
	public void testLookup() {
		Context c=Context.createWith("foo",Constant.create(1));
		Node<?> e=analyse("foo");
		assertEquals(Integer.valueOf(1),e.compute(c));
		
		try {
			e.compute(Context.EMPTY);
			fail("Should not be able to lookup value in empty context");
		} catch (Throwable t) {
			// OK
		}
	}
	
	@Test 
	public void testInfiniteRecursiveLookup() {
		Context c=Context.createWith("foo",Lookup.create("foo"));
		Node<?> e=analyse("foo");
		
		try {
			e.compute(c);
			fail("Should not be able to lookup with inifinite recursion");
		} catch (StackOverflowError t) {
			// OK
		}
	}
	
	@Test 
	public void testConstant() {
		Node<?> e=analyse("1");
		assertEquals(Long.valueOf(1),e.compute(Context.EMPTY));
	}
	
	@Test 
	public void testVector() {
		Context c=Context.createWith("foo",Constant.create(2L));
		Node<?> e=analyse("[1 foo]");
		assertEquals(Tuple.of(1L,2L),e.compute(c));
	}
	
	@Test 
	public void testEmptyVector() {
		Node<?> e=analyse("[]");
		assertEquals(Tuple.EMPTY,e.compute(Context.EMPTY));
	}
	
	@Test 
	public void testEmptyList() {
		Node<?> e=analyse("()");
		assertEquals(PersistentList.EMPTY,e.compute(Context.EMPTY));
	}
	
	@Test 
	public void testLambda() {
		Node<?> e=analyse("(fn [a] a)");
		assertEquals(Lambda.class,e.getClass());
		Context c=Context.createWith("identity",e);
		Node<?> app=analyse("(identity 2)");
		assertEquals(Long.valueOf(2),app.compute(c));

	}

}

@@ -321,16 +321,66 @@
 ntList;%0A
+import magic.data.Sets;%0Aimport magic.data.Symbol;%0A
 import m
@@ -1308,32 +1308,509 @@
 t.EMPTY));%0A%09%7D%0A%09%0A
+%09@Test%0A%09public void testDeps() %7B%0A%09%09Symbol foo=Symbol.create(%22foo%22);%0A%09%09Symbol bar=Symbol.create(%22bar%22);%0A%09%09assertEquals(Sets.of(foo),Analyser.analyse(Reader.read(%22foo%22)).getDependencies());%0A%09%09assertEquals(Sets.of(foo,bar),Analyser.analyse(Reader.read(%22%5Bfoo bar%5D%22)).getDependencies());%0A%09%09assertEquals(Sets.of(),Analyser.analyse(Reader.read(%22(fn %5Bbar%5D bar)%22)).getDependencies());%0A%09%09assertEquals(Sets.of(foo),Analyser.analyse(Reader.read(%22(fn %5Bbar%5D foo)%22)).getDependencies());%0A%09%7D%0A%09%0A
 %09@Test %0A%09public 

Add tests for analysed dependencies