package nl.utwente.viskell.haskell.expr; import nl.utwente.viskell.ghcj.HaskellException; import nl.utwente.viskell.haskell.env.Environment; import nl.utwente.viskell.haskell.type.Type; import nl.utwente.viskell.haskell.type.TypeScope; import org.junit.Before; import org.junit.Test; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.mockito.AdditionalMatchers.not; public class ApplyTest { private final Type integer = Type.con("Int"); private final Type integerList = Type.listOf(this.integer); private final Type string = Type.con("String"); private final Type stringList = Type.listOf(this.string); private Environment env; @Before public final void setUp() { this.env = new Environment(); this.env.addTestSignature("id", "a -> a"); this.env.addTestSignature("(+)", "Int -> Int -> Int"); this.env.addTestSignature("map", "(a -> b) -> [a] -> [b]"); this.env.addTestSignature("zip", "[a] -> [b] -> [(a, b)]"); this.env.addTestSignature("lcm", "a -> a -> a"); } @Test public final void testId() throws HaskellException { final Apply apply = new Apply(this.env.useFun("id"), new Value(this.integer, "42")); assertEquals("(id (42))", apply.toHaskell()); assertEquals(this.integer.prettyPrint(), apply.inferType().prettyPrint()); } @Test public final void testAdd() throws HaskellException { final Apply apply1 = new Apply(this.env.useFun("(+)"), new Value(this.integer, "42")); final Apply apply2 = new Apply(apply1, new Value(this.integer, "42")); assertEquals("((+) (42))", apply1.toHaskell()); assertEquals("(((+) (42)) (42))", apply2.toHaskell()); assertEquals(Type.fun(this.integer, this.integer).prettyPrint(), apply1.inferType().prettyPrint()); assertEquals(this.integer.prettyPrint(), apply2.inferType().prettyPrint()); } @Test public final void testMap() throws HaskellException { final Apply apply0 = new Apply(this.env.useFun("(+)"), new Value(this.integer, "42")); final Apply apply1 = new Apply(this.env.useFun("map"), apply0); final Apply apply2 = new Apply(apply1, new Value(this.integerList, "[1, 2, 3, 5, 7]")); assertEquals("(map ((+) (42)))", apply1.toHaskell()); assertEquals("((map ((+) (42))) ([1, 2, 3, 5, 7]))", apply2.toHaskell()); assertEquals(Type.fun(this.integerList, this.integerList).prettyPrint(), apply1.inferType().prettyPrint()); assertEquals(this.integerList.prettyPrint(), apply2.inferType().prettyPrint()); } @Test public final void testZip() throws HaskellException { TypeScope scope = new TypeScope(); final Type beta = scope.getVar("b"); final Type betaList = Type.listOf(beta); final Apply apply1 = new Apply(this.env.useFun("zip"), new Value(this.integerList, "[1, 2, 3, 5, 7]")); final Apply apply2 = new Apply(apply1, new Value(this.stringList, "[\"a\", \"b\", \"c\"]")); assertEquals("(zip ([1, 2, 3, 5, 7]))", apply1.toHaskell()); assertEquals("((zip ([1, 2, 3, 5, 7])) ([\"a\", \"b\", \"c\"]))", apply2.toHaskell()); assertEquals(Type.fun(betaList, Type.listOf(Type.tupleOf(this.integer, beta))).prettyPrint(), apply1.inferType().prettyPrint()); assertEquals(Type.listOf(Type.tupleOf(this.integer, this.string)).prettyPrint(), apply2.inferType().prettyPrint()); } @Test(expected=HaskellException.class) public final void testIncorrectLcm() throws HaskellException { final Apply apply1 = new Apply(this.env.useFun("lcm"), new Value(this.integer, "42")); final Apply apply2 = new Apply(apply1, new Value(this.string, "\"haskell\"")); assertEquals("(lcm (42))", apply1.toHaskell()); assertEquals("((lcm (42)) (\"haskell\"))", apply2.toHaskell()); assertEquals(Type.fun(this.integer, this.integer).prettyPrint(), apply1.inferType().prettyPrint()); assertThat(this.string, is(not(apply2.inferType().prettyPrint()))); assertThat(this.integer, is(not(apply2.inferType().prettyPrint()))); } }