Permalink
Browse files

informative test output

  • Loading branch information...
TiarkRompf committed Oct 5, 2017
1 parent 2c4d8ec commit ee7d79c9ff01e21dda130114ddc5c88facc61f1d
Showing with 125 additions and 27 deletions.
  1. +47 −0 popl18/base.scala
  2. +1 −0 popl18/bench.scala
  3. +33 −26 popl18/lisp.scala
  4. +4 −0 popl18/matcher.scala
  5. +37 −1 popl18/pink.scala
  6. +3 −0 popl18/test-main.scala
@@ -139,6 +139,8 @@ object Base {
val (Code(u),Code(v)) = (a,b)
reflect(Cons(u,v))
case Clo(env2,e2) => // function
// NOTE: We memoize functions here. This is not essential, and
// could be removed, yielding exactly the code shown in the paper.
stFun collectFirst { case (n,`env2`,`e2`) => n } match {
case Some(n) =>
Var(n)
@@ -309,11 +311,56 @@ object Base {
case _ => e.toString
}

var testsRun = 0
def testDone(): Unit = {
println(s" Tests run: $testsRun"); testsRun = 0
}

def check(a:Any)(s:String) = if (a.toString.trim != s.trim) {
println("error: expected ")
println(" "+s)
println("but got")
println(" "+a)
(new AssertionError).printStackTrace
} else testsRun += 1


// basic test cases
def test() = {
println("// ------- Base.test --------")
println("Staged factorial...")
/*
pattern:
def f = fun { n => if (n != 0) f(n-1) else 1 }
corresponds to:
val f = { () => lift({ n => if (n != 0) f()(n-1) else 1 }) }
*/
val f_self = App(Var(0),Lit(99))
val n = Var(3)

val fac_body = Lam(If(n,Times(n,App(f_self,Minus(n,Lift(Lit(1))))),Lift(Lit(1))))
val fac = App(Lam(Lift(fac_body)),Lit(99))
val code = reifyc(evalms(Nil,fac))
val out =
Let(Lam(
Let(If(Var(1),
Let(Minus(Var(1),Lit(1)),
Let(App(Var(0),Var(2)),
Let(Times(Var(1),Var(3)),
Var(4)))),
/* else */
Lit(1)
),
Var(2))),
Var(0))

check(code)(out.toString)

check(evalms(Nil,App(code,Lit(4))))("Cst(24)")

testDone()
}


}
@@ -16,6 +16,7 @@ object Bench {
}

def test() = {
println("// ------- Bench.test --------")
println("fac #,evaluated,compiled,traced evaluated,traced compiled")
val oldLog = Base.log
try {
@@ -5,7 +5,7 @@ object Lisp {

import scala.util.parsing.combinator._

// adapted from github.com/namin/lms-black
// s-expr parser
object parser extends JavaTokenParsers with PackratParsers {
override val whiteSpace = """(\s|(;[^\n]*))+""".r

@@ -32,36 +32,36 @@ object Lisp {
v
}

// ********************* convert exp encoded as val --> exp *********************
// ********************* convert exp encoded as val --> proper exp *********************

def trans(e: Val, env: List[String]): Exp = e match {
case Cst(n) => Lit(n)
case Str(s) => val i = env.lastIndexOf(s); assert(i>=0, s + " not in " + env); Var(i)
case Tup(Str("quote"),Tup(Str(s),N)) => Sym(s)
case Tup(Str("+"),Tup(a,Tup(b,N))) => Plus(trans(a,env),trans(b,env))
case Tup(Str("-"),Tup(a,Tup(b,N))) => Minus(trans(a,env),trans(b,env))
case Tup(Str("*"),Tup(a,Tup(b,N))) => Times(trans(a,env),trans(b,env))
case Tup(Str("quote"), Tup(Str(s),N)) => Sym(s)
case Tup(Str("+"), Tup(a,Tup(b,N))) => Plus(trans(a,env),trans(b,env))
case Tup(Str("-"), Tup(a,Tup(b,N))) => Minus(trans(a,env),trans(b,env))
case Tup(Str("*"), Tup(a,Tup(b,N))) => Times(trans(a,env),trans(b,env))
// (let x a b)
case Tup(Str("let"),Tup(Str(x),Tup(a,Tup(b,N)))) => Let(trans(a,env),trans(b,env:+x))
case Tup(Str("let"), Tup(Str(x),Tup(a,Tup(b,N)))) => Let(trans(a,env),trans(b,env:+x))
// (lambda f x e)
case Tup(Str("lambda"),Tup(Str(f),Tup(Str(x),Tup(e,N)))) => Lam(trans(e,env:+f:+x))
case Tup(Str("if"),Tup(c,Tup(a,Tup(b,N)))) => If(trans(c,env),trans(a,env),trans(b,env))
case Tup(Str("num?"),Tup(a,N)) => IsNum(trans(a,env))
case Tup(Str("sym?"),Tup(a,N)) => IsStr(trans(a,env))
case Tup(Str("pair?"),Tup(a,N)) => IsCons(trans(a,env))
case Tup(Str("cons"),Tup(a,Tup(b,N))) => Cons(trans(a,env),trans(b,env))
case Tup(Str("car"),Tup(a,N)) => Fst(trans(a,env))
case Tup(Str("cdr"),Tup(a,N)) => Snd(trans(a,env))
case Tup(Str("cadr"),Tup(a,N)) => Fst(Snd(trans(a,env)))
case Tup(Str("caddr"),Tup(a,N)) => Fst(Snd(Snd(trans(a,env))))
case Tup(Str("cadddr"),Tup(a,N)) => Fst(Snd(Snd(Snd(trans(a,env)))))
case Tup(Str("lift"),Tup(a,N)) => Lift(trans(a,env))
case Tup(Str("nolift"),Tup(a,N)) => trans(a,env)
case Tup(Str("eq?"),Tup(a,Tup(b,N))) => Equs(trans(a,env),trans(b,env))
case Tup(Str("run"),Tup(b,Tup(a,N))) => Run(trans(b,env),trans(a,env))
case Tup(Str("log"),Tup(b,Tup(a,N))) => Log(trans(b,env),trans(a,env))
case Tup(Str("quote"),Tup(a,N)) => Special(benv => a)
case Tup(Str("exec"),Tup(b,Tup(a,N))) =>
case Tup(Str("lambda"), Tup(Str(f),Tup(Str(x),Tup(e,N)))) => Lam(trans(e,env:+f:+x))
case Tup(Str("if"), Tup(c,Tup(a,Tup(b,N)))) => If(trans(c,env),trans(a,env),trans(b,env))
case Tup(Str("num?"), Tup(a,N)) => IsNum(trans(a,env))
case Tup(Str("sym?"), Tup(a,N)) => IsStr(trans(a,env))
case Tup(Str("pair?"), Tup(a,N)) => IsCons(trans(a,env))
case Tup(Str("cons"), Tup(a,Tup(b,N))) => Cons(trans(a,env),trans(b,env))
case Tup(Str("car"), Tup(a,N)) => Fst(trans(a,env))
case Tup(Str("cdr"), Tup(a,N)) => Snd(trans(a,env))
case Tup(Str("cadr"), Tup(a,N)) => Fst(Snd(trans(a,env)))
case Tup(Str("caddr"), Tup(a,N)) => Fst(Snd(Snd(trans(a,env))))
case Tup(Str("cadddr"), Tup(a,N)) => Fst(Snd(Snd(Snd(trans(a,env)))))
case Tup(Str("lift"), Tup(a,N)) => Lift(trans(a,env))
case Tup(Str("nolift"), Tup(a,N)) => trans(a,env)
case Tup(Str("eq?"), Tup(a,Tup(b,N))) => Equs(trans(a,env),trans(b,env))
case Tup(Str("run"), Tup(b,Tup(a,N))) => Run(trans(b,env),trans(a,env))
case Tup(Str("log"), Tup(b,Tup(a,N))) => Log(trans(b,env),trans(a,env))
case Tup(Str("quote"), Tup(a,N)) => Special(benv => a)
case Tup(Str("exec"), Tup(b,Tup(a,N))) =>
// Note: the only difference with Run is that we use benv instead of Nil
// below for outer evalms of the non-Code case.
def f(b: Exp, a: Exp): Special = Special(benv =>
@@ -70,7 +70,7 @@ object Lisp {
case _ => evalms(benv, reifyc(evalms(benv, a)))
})
f(trans(b, env), trans(a, env))
case Tup(Str("trans"),Tup(a,N)) =>
case Tup(Str("trans"), Tup(a,N)) =>
Special(benv => Code(trans(evalms(benv, trans(a,env)), env)))
case Tup(Str("lift-ref"),Tup(a,N)) =>
Special(benv => Code(Special(b2 => evalms(benv,trans(a,env)))))
@@ -106,4 +106,11 @@ object Lisp {
Base.log = oldLog
}
}

// basic test cases
def test() = {
println("// ------- Lisp.test --------")
// all tested in Pink.test ...
testDone()
}
}
@@ -25,6 +25,8 @@ match)))"""
val matcherc_src = s"(let maybe-lift (lambda _ e (lift e)) $matcher_poly_src)"

def test() = {
println("// ------- Matcher.test --------")

checkrun(s"(($matcher_src '(_ * a _ * done)) '(b a done))", "Str(yes)")
checkrun(s"(($matcher_src '(_ * a _ * done)) '(b b done))", "Str(no)")
checkrun(s"((run 0 ($matcherc_src '(_ * a _ * done))) '(b a done))", "Str(yes)")
@@ -90,5 +92,7 @@ match)))"""
checkrunlog(s"((run 0 ((run 0 ($instrc_src '$matcherc_src)) '(a b done))) '(a b done))", "Str(yes)", logres)
checkcode(s"(($instr2_src '$matcherc_src) '(a b done))", log_ab_code)
checkcode(s"((run 0 ($instrc_src '$matcherc_src)) '(a b done))", log_ab_code)

testDone()
}
}
@@ -57,12 +57,14 @@ object Pink {
val evalc_exp_anf = reify { anf(List(Sym("XX")),evalc_exp1) }

def test() = {
println("// ------- Pink.test --------")
testCorrectnessOptimality()
testInstrumentation()
testEM()
}

def testCorrectnessOptimality() = {
println("Correctness and optimality...")
// direct execution
checkrun(s"""
(let fac $fac_src
@@ -150,11 +152,16 @@ object Pink {
(let x2 (- x1 1)
(let x3 (f0 x2) (* x1 x3)))
1))""")

testDone()
}

val evt_poly_src = ev_poly_src.replace("(env exp)", "(if (eq? 'n exp) (log (maybe-lift 0) (env exp)) (env exp))")
val trace_n_evalc_src = ev_nil(ev_lift(evt_poly_src))

def testInstrumentation() = {
println("Instrumentation...")

checkcode(s"""
(let trace_n_evalc $trace_n_evalc_src
(let fac_src (quote $fac_src)
@@ -177,6 +184,8 @@ object Pink {
((run 0 (trace_n_evalc fac_src)) 3)))""",
"Cst(6)",
"Cst(3);Cst(3);Cst(3);Cst(2);Cst(2);Cst(2);Cst(1);Cst(1);Cst(1);Cst(0);")

testDone()
}

def addCases(cs: String*): String = {
@@ -195,7 +204,10 @@ object Pink {
val emt_src = """((EM (((lambda ev exp (lambda _ env
(if (if (sym? exp) (eq? 'n exp) 0) (log 0 ((eval exp) env)) (((tie ev) exp) env))))
'(lambda f n (if n (* n (f (- n 1))) 1))) env)) 3)"""

def testEM() = {
println("EM...")

// sanity checks
checkrun(s"""
(let eval0 $eval0_src
@@ -220,6 +232,8 @@ object Pink {
(let emt_src (quote $emt_src)
((eval0 evaln_src) emt_src))))""", "Cst(6)",
"Cst(3);Cst(3);Cst(3);Cst(2);Cst(2);Cst(2);Cst(1);Cst(1);Cst(1);Cst(0);")

testDone()
}
}

@@ -252,6 +266,15 @@ object Pink_CPS {
val evalc_src = ev_nil(ev_lift(ev_poly_src))

def test() = {
println("// ------- Pink_CPS.test --------")

testBasics()
testEM()
}

def testBasics() {
println("Basics...")

// interpretation of fac
checkrun(s"""
(let eval $eval_src
@@ -298,7 +321,7 @@ object Pink_CPS {
(let nested_src (quote $nested_src)
(((run 0 ((evalc nested_src) (lambda _ f f))) 0) (lambda _ x x))))""", "Cst(2)")

testEM()
testDone()
}

def addCases(cs: String*): String = {
@@ -323,6 +346,8 @@ object Pink_CPS {
(+ 3 (call/cc (lambda _ k (k (k (k 1)))))))
"""
def testEM() = {
println("EM...")

// sanity check
checkrun(s"""
(let eval0 $eval0_src
@@ -334,6 +359,8 @@ object Pink_CPS {
(let eval0 $eval0_src
(let emt_src (quote $emt_src)
((eval0 emt_src) (lambda _ x x))))""", "Cst(10)")

testDone()
}
}

@@ -380,6 +407,8 @@ object Pink_clambda {
val fc_src = fac_src.replace("lambda", "clambda")

def test_clambda() = {
println("clambda...")

checkrun(s"""
(let eval $eval_src
(let fc_src (quote $fc_src)
@@ -409,9 +438,13 @@ object Pink_clambda {
(let x5 (x3 x4)
(let x6 (x3 y) (* x5 x6)))))""")
checkcode(s"(((($eval_src (quote $f_src)) 1) 4) (lambda _ z (lift z)))", "(* 2 4)")

testDone()
}

def test_em() {
println("EM...")

val ev_log_src = ev_tie_src.replace("(env exp)", "(if (eq? 'n exp) (log ((car l) 0) (env exp)) (env exp))")
val fac4_trace = "Cst(4);Cst(4);Cst(4);Cst(3);Cst(3);Cst(3);Cst(2);Cst(2);Cst(2);Cst(1);Cst(1);Cst(1);Cst(0);"
def em1(src: String) = s"(EM ((($ev_log_src l) '($src 4)) env))"
@@ -423,9 +456,12 @@ object Pink_clambda {
checkrunlog(s"($eval_src '${em1(fc_src)})" , "Cst(24)", fac4_trace)
checkrunlog(s"($eval_src '${em2(fac_src)})", "Cst(24)", fac4_trace)
checkrunlog(s"($eval_src '${em2(fc_src)})" , "Cst(24)", fac4_trace)

testDone()
}

def test() = {
println("// ------- Pink_clambda.test --------")
test_clambda()
test_em()
}
@@ -1,9 +1,12 @@
object TestMain {
def main(args: Array[String]) {
Base.test()
Lisp.test()
Pink.test()
Pink_CPS.test()
Pink_clambda.test()
Matcher.test()
Bench.test()
println("DONE")
}
}

0 comments on commit ee7d79c

Please sign in to comment.