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;
}
}