aboutsummaryrefslogtreecommitdiff
path: root/src/test/scala/Tests.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/scala/Tests.scala')
-rw-r--r--src/test/scala/Tests.scala203
1 files changed, 203 insertions, 0 deletions
diff --git a/src/test/scala/Tests.scala b/src/test/scala/Tests.scala
new file mode 100644
index 0000000..1c28875
--- /dev/null
+++ b/src/test/scala/Tests.scala
@@ -0,0 +1,203 @@
+import utest._
+import utest.ExecutionContext
+import cl._
+
+object Tests extends TestSuite {
+ val tests = TestSuite {
+ val p: Var = 'p
+ val q: Var = 'q
+ val r: Var = 'r
+ val s: Var = 's
+
+ 'usage {
+ val pq = p * q
+ val pqr = p * q * r
+ val pqrs = p * q * r * s
+ val parens = p * (q * r) * s
+ val nested = p * (parens) * s
+ val nestedLeft = (((p * q) * r) * s)
+ val nestedRight = (p * (q * (r * s)))
+
+ 'toString {
+ assert(
+ pq.toString == "pq",
+ pqr.toString == "pqr",
+ pqrs.toString == "pqrs",
+ parens.toString == "p(qr)s",
+ nested.toString == "p(p(qr)s)s",
+ nestedLeft.toString == "pqrs",
+ nestedRight.toString == "p(q(rs))"
+ )
+ }
+
+ 'equality {
+ "non-commutative"-{
+ assert(
+ p * q == p * q,
+ p * q != q * p
+ )
+ }
+
+ "non-associative"-{
+ assert(p * (q*r) != (p*q) * r)
+ }
+
+ "left-associative"-{
+ assert(
+ p * q * r * s == (((p*q) * r) * s),
+ p * q * r * s != (p * (q * (r*s)))
+ )
+ }
+ }
+
+ "contains"-{
+ assert(
+ pq.contains(p),
+ pq.contains(q),
+ !pq.contains(r),
+ nestedRight.contains(s)
+ )
+ }
+ }
+
+ "reduction"-{
+ /*
+ "Evaluation is complete when..."-{
+ "...the term begins with a var"-{
+ val vars = s*s*s*s*s*s
+ assert(
+ eval(s) == s,
+ eval(s*s) == s*s,
+ eval(vars) == (vars),
+ eval(s * K * p * q) == (s * K * p * q)
+ )
+ }
+
+ "...the leading combinator has too few arguments for reduction"-{
+ assert(
+ eval(K) == K,
+ eval(K * p) == K * p,
+ eval(K * p * p) == p
+ )
+ }
+ }
+
+ "basic combinators"-{
+ assert(
+ eval(I * p) == p,
+ eval(K * p * q) == p,
+ eval(S * p * q * r) == p * r * (q * r)
+ )
+ }
+
+ "head reduction"-{
+ // NOTE: Implementing head reduction separately is optional,
+ // but could be a helpful first step.
+ assert(
+ //evalHead(K * p * q * r * s) == p * r * s,
+ //evalHead(K * p * q * K * p * q) == p * K * p * q,
+ //evalHead(K * I * p * q) == I * q
+ )
+ }
+
+ "step by step reduction"-{
+ /*assert(
+ evalHead(S * (K * S) * K * p * q * r) == (S * (K * S) * K * p * q),
+ evalHead(S * (K * S) * K * p * q) == (K * S * p * (K * p) * q),
+ evalHead(K * S * p * (K * p) * q) == (S * (K * p) * q),
+ evalHead(S * (K * p) * q) == (S * (K * p) * q * r),
+ evalHead(S * (K * p) * q * r) == (K * p * r * (q * r)),
+ evalHead(K * p * r * (q * r)) == (p * (q * r))
+ )*/
+ }
+
+ "complete reduction"-{
+ assert(
+ eval(S * (K * S) * K * p * q * r) == p * (q * r),
+ eval(Sp * K * I * I * s) == s,
+ eval(B * (B * S) * B * K * I * I * s) == s,
+ eval(S*(K*S)*K * (S*(K*S)*K * S) * (S*(K*S)*K) * K * (S*K*K) * I * s) == s
+ )
+ }
+ */
+ }
+
+ "bracket abstraction"-{
+ /*
+ val TRUE = K
+ val FALSE = K*I
+
+ def evalBool(bool: Term): Boolean = {
+ val p: Var = 'P
+ val q: Var = 'Q
+ // if bool then p else q
+ eval(bool * p * q) match {
+ case x if x == p => true
+ case x if x == q => false
+ }
+ }
+
+ "Booleans evaluating properly"-{
+ assert(
+ evalBool(TRUE),
+ !evalBool(FALSE)
+ )
+ }
+
+ def not = (p: Term) => p * FALSE * TRUE
+ def and = (p: Term, q: Term) => p * q * FALSE
+ def or = (p: Term, q: Term) => p * TRUE * q
+
+ "basic boolean functions"-{
+ assert(
+ evalBool(not(FALSE)),
+ !evalBool(not(TRUE)),
+
+ evalBool(and(TRUE, TRUE)),
+ !evalBool(and(TRUE, FALSE)),
+ !evalBool(and(FALSE, TRUE)),
+ !evalBool(and(FALSE, FALSE)),
+
+ evalBool(or(TRUE, TRUE)),
+ evalBool(or(TRUE, FALSE)),
+ evalBool(or(FALSE, TRUE)),
+ !evalBool(or(FALSE, FALSE))
+ )
+ }
+
+ "variable extraction"-{
+ val x: Var = 'x
+ val term = not(x).extract(x)
+
+ assert(
+ not(x).contains(x),
+ !term.contains(x),
+ evalBool(term * TRUE) == evalBool(not(TRUE)),
+ evalBool(term * FALSE) == evalBool(not(FALSE))
+ )
+ }
+
+ "boolean functions abstracted"-{
+ val NOT: Term = bracketAbstraction(not)
+ val AND: Term = bracketAbstraction(and)
+ val OR: Term = bracketAbstraction(or)
+
+ assert(
+ evalBool(NOT * FALSE),
+ !evalBool(NOT * TRUE),
+
+ evalBool(AND * TRUE * TRUE),
+ !evalBool(AND * TRUE * FALSE),
+ !evalBool(AND * FALSE * TRUE),
+ !evalBool(AND * FALSE * FALSE),
+
+ evalBool(OR * TRUE * TRUE),
+ evalBool(OR * TRUE * FALSE),
+ evalBool(OR * FALSE * TRUE),
+ !evalBool(OR * FALSE * FALSE)
+ )
+ }
+ */
+ }
+ }
+}