package scotch.compiler.analyzer; import static java.util.Arrays.asList; import static scotch.compiler.syntax.StubResolver.defaultEq; import static scotch.compiler.syntax.StubResolver.defaultPlus; import static scotch.compiler.syntax.value.Values.apply; import static scotch.util.TestUtil.arg; import static scotch.util.TestUtil.capture; import static scotch.util.TestUtil.equal; import static scotch.util.TestUtil.id; import static scotch.util.TestUtil.literal; import static scotch.util.TestUtil.matcher; import static scotch.util.TestUtil.pattern; import static scotch.util.TestUtil.valueRef; import static scotch.symbol.Symbol.qualified; import static scotch.symbol.SymbolEntry.immutableEntry; import static scotch.compiler.syntax.type.Types.fn; import static scotch.compiler.syntax.type.Types.sum; import static scotch.compiler.syntax.type.Types.t; import static scotch.compiler.syntax.type.Types.var; import java.util.function.Function; import org.junit.Ignore; import org.junit.Test; import scotch.compiler.Compiler; import scotch.compiler.IsolatedCompilerTest; import scotch.compiler.syntax.definition.DefinitionGraph; public class SyntaxParseIntegrationTest extends IsolatedCompilerTest { @Test public void shouldShufflePattern() { resolver.define(immutableEntry(qualified("scotch.data.bool", "not")).build()); compile( "module scotch.test", "import scotch.data.bool", "left infix 6 (==), (/=)", "x == y = not (x /= y)" ); shouldHaveValue("scotch.test.(==)", matcher("scotch.test.(==#0)", t(9), asList(arg("#0", t(7)), arg("#1", t(8))), pattern("scotch.test.(==#0#0)", asList(capture(arg("#0", t(10)), "x", t(0)), capture(arg("#1", t(11)), "y", t(2))), apply( id("scotch.data.bool.not", t(3)), apply( apply(id("scotch.test.(/=)", t(5)), id("x", t(4)), t(12)), id("y", t(6)), t(13) ), t(14) )) )); } @Test public void shouldConsolidatePatternsIntoSingleValue() { compile( "module scotch.test", "left infix 8 (+), (-)", "fib 0 = 0", "fib 1 = 1", "fib n = fib (n - 1) + fib (n - 2)" ); shouldHaveValue("scotch.test.fib", matcher("scotch.test.(fib#0)", t(12), asList(arg("#0", t(11))), pattern("scotch.test.(fib#0#0)", asList(equal(arg("#0", t(13)), literal(0))), literal(0)), pattern("scotch.test.(fib#0#1)", asList(equal(arg("#0", t(14)), literal(1))), literal(1)), pattern("scotch.test.(fib#0#2)", asList(capture(arg("#0", t(15)), "n", t(3))), apply( apply( id("scotch.test.(+)", t(7)), apply( id("scotch.test.fib", t(4)), apply( apply(id("scotch.test.(-)", t(6)), id("n", t(5)), t(16)), literal(1), t(17) ), t(18) ), t(22) ), apply( id("scotch.test.fib", t(8)), apply( apply(id("scotch.test.(-)", t(10)), id("n", t(9)), t(19)), literal(2), t(20) ), t(21) ), t(23) )) )); } @Test public void shouldQualifySiblingValues() { resolver .define(defaultPlus()) .define(defaultEq()); compile( "module scotch.test", "import scotch.data.eq", "import scotch.data.num", "fn a b = a + b == b + a", "commutative? a b = fn a b" ); shouldNotHaveErrors(); shouldHaveValue("scotch.test.(commutative?)", matcher("scotch.test.(commutative?#0)", t(29), asList(arg("#0", t(27)), arg("#1", t(28))), pattern( "scotch.test.(commutative?#0#0)", asList(capture(arg("#0", t(30)), "a", t(11)), capture(arg("#1", t(31)), "b", t(12))), apply( apply( id("scotch.test.fn", t(13)), id("a", t(14)), t(32) ), id("b", t(15)), t(33) ) ) )); } @Ignore @Test public void shouldParseTypeClass() { compile( "module scotch.test", "import scotch.data.bool", "class Eq a where", " (==), (/=) :: a -> a -> Bool", " x == y = not $ x /= y", " x /= y = not $ x == y" ); shouldHaveClass("scotch.test.Eq", asList(var("a")), asList( valueRef("scotch.test.(==)"), valueRef("scotch.test.(/=)"), valueRef("scotch.test.(==)"), valueRef("scotch.test.(/=)") )); shouldHaveValue("scotch.test.(==)", fn(var("a", asList("Eq")), fn(var("a", asList("Eq")), sum("Bool")))); } @Override protected Function<scotch.compiler.Compiler, DefinitionGraph> compile() { return Compiler::qualifyNames; } }