package magic.core;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

import magic.Core;
import magic.data.Symbol;
import magic.data.Tuple;
import magic.lang.Context;
import magic.lang.Slot;

public class TestEdgeCases {
	@SuppressWarnings("unchecked")
	private <T> T exec(String code) {
		return (T) Core.eval(code).getValue();
	}
	
	@Test public void testDefUnquote() {
		// unquote should create a symbol that can be used with def
		assertEquals((Long)2L,exec("(def ~'a 2) a"));
		assertEquals((Long)2L,exec("(def ~(symbol \"a\") 2) a"));
	}
	
	@Test public void testArgUnquote() {
		// unquote should create a symbol that can be used in parameter vector
		assertEquals((Long)3L,exec(
				"(defn foo [~'a] (+ 2 a)) "
				+ "(foo 1)"));
	}
	
	@Test public void testContextTravel() {
		assertEquals(Tuple.of(1L),exec(
				  "(def a 1) "
				+ "(def ctx *context*)"
				+ "(def a 2)"
				+ "(context ctx)"
				+ "[a]"));
	}
	
	@Test public void testRecursiveFunction() {
		Context c=Core.eval("(defn fact [a] "
				+ "  (if (<= a 1) 1 (* a (fact (dec a)))))").getContext();
		Slot<?> s=c.getSlot("fact");
		assertEquals(Symbol.createSet("magic.core/fact","magic.core/fn","magic.core/<=","magic.core/if","magic.core/*","magic.core/dec"),s.getDependencies());
		assertEquals(Tuple.of(24L),Core.eval(c,"[(fact 4)]").getValue());
	}
	
	@Test public void testNS() {
		assertEquals("foo.bar",exec(
				  "(ns foo.bar) "
				+ "magic.core/*ns*"));
	}
}

@@ -932,32 +932,318 @@
 + %22%5Ba%5D%22));%0A%09%7D%0A%09%0A
+%09@Test public void testCapture() %7B%0A%09%09Context c=Core.eval(%22(defn adder %5Bx%5D (fn %5Ba%5D (+ a x)))%22+%0A%09%09%09%09%09%09%09%22(def add2 (adder 2))%22+%0A%09%09%09%09%09%09%09%22(def add3 (adder 3))%22).getContext();%0A%09%09assertEquals(9L,Core.eval(c,%22(add2 7)%22).getValue());%0A%09%09assertEquals(10L,Core.eval(c,%22(add3 7)%22).getValue());%0A%09%7D%0A%09%0A
 %09@Test public vo

Test for variable capture