import lib._
import turing._
import abacus._
import recs._
import comp1._
import comp2._
// Turing machine examples
val TMCopy = TM((WBk, 5), (R, 2), (R, 3), (R, 2), (WOc, 3),
(L, 4), (L, 4), (L, 5), (R, 11), (R, 6),
(R, 7), (WBk, 6), (R, 7), (R, 8), (WOc, 9),
(R, 8), (L, 10), (L, 9), (L, 10), (L, 5),
(L, 0), (R, 12), (WOc, 13), (L, 14), (R, 12),
(R, 12), (L, 15), (WBk, 14), (R, 0), (L, 15))
println("TMCopy: " + (TMCopy.run(Tape(3))))
println("TMfindnth: " + (TMFindnth(3).run(Tape(1,2,3,4,5))))
println("TMMopup: " + (TMMopup(3).run(Tape(1,2,3,4,5))))
// Abacus machine examples
def Copy(in: Int, out: Int, jump: Int) =
Abacus(Dec(in, jump), Inc(out), Goto(0))
def Plus(m: Int, n: Int, tmp: Int, jump: Int) =
Abacus(Dec(m, 4), Inc(n), Inc(tmp), Goto(0), Dec(tmp, jump), Inc(m), Goto(4))
def Mult(in1: Int, in2: Int, out: Int, tmp: Int, jump: Int) =
Abacus(Dec(in1, jump)) ++ Plus(in2, out, tmp, -1).shift(1, -1).adjust(-1, 0)
def Expo(in1: Int, in2: Int, out: Int, tmp1: Int, tmp2: Int, jump: Int) = {
Abacus(Inc(out), Dec(in1, jump)) ++
Mult(out, in2, tmp2, tmp1, -1).shift(2, -1).adjust(-1, 10) ++
Copy(tmp2, out, -1).shift(10, -1).adjust(-1, 1)
}
println("Copy 3: " + (Copy(0, 1, -1).run(Map(0 -> 3, 1 -> 0))))
println("Plus 3 + 4: " + (Plus(0, 1, 2, -1).run(Map(0 -> 3, 1 -> 4, 2 -> 0))))
println("Mult 3 * 5: " + (Mult(0, 1, 2, 3, -1).run(Map(0 -> 3, 1 -> 5, 2 -> 0, 3 -> 0))))
println("Expo 3 ^ 4: " + (Expo(0, 1, 2, 3, 4, -1).run(Map(0 -> 4, 1 -> 3, 2 -> 0, 3 -> 0, 4 -> 0))))
// Abacus-to-TM translation examples
println("Compiled Copy 3: " + toTM(Copy(0, 1, Int.MaxValue).p).run(Tape(3,0,0)))
println("Compiled Plus 3 + 4: " + toTM(Plus(0, 1, 2, Int.MaxValue).p).run(Tape(3,4,0,0)))
println("Compiled Mult 3 * 5: " + toTM(Mult(0, 1, 2, 3, Int.MaxValue).p).run(Tape(3,5,0,0)))
println("Compiled Expo 3 ^ 4: " + toTM(Expo(0, 1, 2, 3, 4, 10000).p).run(Tape(3,4,0,0,0)))
// Recursive function examples
println("Add 3 4: " + Add.eval(3, 4))
println("Mult 3 4: " + recs.Mult.eval(3, 4))
println("Twice 4: " + Twice.eval(4))
println("FourTm 4: " + Fourtimes.eval(4))
println("Pred 9: " + Pred.eval(9))
println("Pred 0: " + Pred.eval(0))
println("Minus 6 2: " + Minus.eval(6, 2))
println("Minus 6 8: " + Minus.eval(6, 8))
println("Const 8: " + Const(8).eval(67))
println("Power 2 3: " + Power.eval(2, 3))
println("Sign 8: " + Sign.eval(8))
println("Sign 0: " + Sign.eval(0))
println("Less 4 4: " + Less.eval(4, 4))
println("Less 4 6: " + Less.eval(4, 6))
println("Less 6 4: " + Less.eval(6, 4))
println("Not 0: " + Not.eval(0))
println("Not 6: " + Not.eval(6))
println("Eq 4 4: " + Eq.eval(4, 4))
println("Eq 4 6: " + Eq.eval(4, 6))
println("Eq 6 4: " + Eq.eval(6, 4))
println("Conj 0 6: " + Conj.eval(0, 6))
println("Conj 6 4: " + Conj.eval(6, 4))
println("Conj 0 0: " + Conj.eval(0, 0))
println("Disj 0 6: " + Disj.eval(0, 6))
println("Disj 6 4: " + Disj.eval(6, 4))
println("Disj 0 0: " + Disj.eval(0, 0))
println("Sigma Add 2 3 -> 14: " + Sigma(Add).eval(2,3))
println("Accum Add 2 3 -> 120: " + Accum(Add).eval(2,3))
println("Accum Mult 2 3 -> 0: " + Accum(recs.Mult).eval(2,3))
println("Fact 5: " + Fact.eval(5))
println("Prime 0..15: " + (0 to 15).map(n => (n, Prime.eval(n))))
println("NextPrime 3: " + NextPrime.eval(3))
println("NthPrime 1: " + NthPrime.eval(1))
println("Listsum [2, 3, 4 , 5, 6]: " + Listsum(5, 4).eval(2, 3, 4, 5, 6))
println("Strt: " + Strt(2).eval(2,3))
// compilation of rec to abacus tests
def test_comp2(f: Rec, ns: Int*) = {
val (abc_f, arity, _) = compile_rec(f)
val abc_map = (0 until ns.length).zip(ns).toMap[Int, Int]
val res = (abc_f.run(abc_map))(arity)
("Result: " + res + " length: " + abc_f.p.length)
}
println("S(3) " + test_comp2(S, 3))
println("Const(1) " + test_comp2(Const(1), 0))
println("Const(10) " + test_comp2(Const(10), 0))
println("Add(69, 30) " + test_comp2(Add, 69, 30))
println("Mult(13, 9) " + test_comp2(recs.Mult, 13, 9))
println("Power(3, 4) " + test_comp2(Power, 3, 4))
println("Minus(30, 4) " + test_comp2(Minus, 30, 4))
println("Fact(5) " + test_comp2(Fact, 5))
println("Prime(5) " + test_comp2(Prime, 5))
println("Prime(6) " + test_comp2(Prime, 6))
println("Strt(1)(2) " + test_comp2(Strt(1), 2))
//println(toTM(compile_rec(Add)._1.p).run(Tape(3, 4, 0)))
//println(compile_rec(Add)._1.run(Map(0 -> 3, 1 -> 8, 2 -> 0)))
//compile_rec(Add)._1.run(Map(0 -> 3, 1 -> 4, 2 -> 0))