Commit a33194fe authored by Luca Bataillard's avatar Luca Bataillard
Browse files

Finish first non trivial implementation of tail

All tests pass, though I'm not sure it's a fully optimal solution, especially with the second S.Prim
and S.Halt
parent d10e6c58
......@@ -9,9 +9,6 @@ object CL3ToCPSTranslator extends (S.Tree => C.Tree) {
C.Halt(C.AtomL(IntLit(L3Int(0))))
)
def tail(tree: S.Tree)(c: C.Name): C.Tree =
nonTail(tree)(v => C.AppC(c, Seq(v)))
def cond(condition: S.Tree)(thnCnt: C.Name, elsCnt: C.Name): C.Tree = {
def transformTestPrim(p: L3TestPrimitive, args: Seq[S.Tree]): C.Tree = {
......@@ -57,6 +54,62 @@ object CL3ToCPSTranslator extends (S.Tree => C.Tree) {
}
}
}
def tail(tree: S.Tree)(c: C.Name): C.Tree = {
def tailApp(fun: S.Tree, args: Seq[S.Tree]) = {
def tailFunArgs(args: Seq[S.Tree])(fId: C.Atom, ids: Seq[C.Atom]): C.Tree = args match {
case Nil => C.AppF(fId, c, ids)
case arg :: args => nonTail(arg)(v => tailFunArgs(args)(fId, ids :+ v))
}
nonTail(fun)(fId => tailFunArgs(args)(fId, Seq()))
}
def tailLetRec(funs: Seq[S.Fun], body: S.Tree) = {
val cpsFuns = funs map { case S.Fun(name, args, body) =>
val cName = Symbol.fresh("c-" + name)
C.Fun(name, cName, args, tail(body)(cName))
}
C.LetF(cpsFuns, tail(body)(c))
}
tree match {
case S.Let(bindings, body) => bindings.foldRight(tail(body)(c)) {
case ((name, expr), tree) => nonTail(expr)(v => C.LetP(name, L3.Id, Seq(v), tree))
}
case S.If(condition, thn, els) => {
val thnCntName = Symbol.fresh("ct")
val thnCntBody = tail(thn)(c)
val thnCnt = C.Cnt(thnCntName, Seq(), thnCntBody)
val elsCntName = Symbol.fresh("cf")
val elsCntBody = tail(els)(c)
val elsCnt = C.Cnt(elsCntName, Seq(), elsCntBody)
val ifBody = cond(condition)(thnCntName, elsCntName)
C.LetC(Seq(thnCnt), C.LetC(Seq(elsCnt), ifBody))
}
case S.App(fun, args) => tailApp(fun, args)
case S.LetRec(funs, body) => tailLetRec(funs, body)
case S.Prim(p: L3TestPrimitive, args) => {
implicit val pos = tree.pos
val newPrim = S.If(tree, S.Lit(BooleanLit(true)), S.Lit(BooleanLit(false)))
tail(newPrim)(c)
}
// The remaining cases (Lit, Ident, value Prim, Halt) should return to non-tail
// since they all use the result value more than just applying the current continuation
case _ => nonTail(tree)(v => C.AppC(c, Seq(v)))
}
}
def nonTail(tree: S.Tree)(ctx: C.Atom => C.Tree): C.Tree = {
......@@ -68,13 +121,13 @@ object CL3ToCPSTranslator extends (S.Tree => C.Tree) {
// Transforms each arg successively, accumulate generated atoms. At bottom create letc-apply
// expression. Return resulting tree
def transformArgs(args: Seq[S.Tree])(fId: C.Atom, ids: Seq[C.Atom]): C.Tree = args match {
def transformFunArgs(args: Seq[S.Tree])(fId: C.Atom, ids: Seq[C.Atom]): C.Tree = args match {
case Nil => C.LetC(Seq(returnCnt), C.AppF(fId, cntName, ids))
case arg :: args => nonTail(arg)(v => transformArgs(args)(fId, ids :+ v))
case arg :: args => nonTail(arg)(v => transformFunArgs(args)(fId, ids :+ v))
}
// Transform initial function then start argument transformation
nonTail(fun)(fId => transformArgs(args)(fId, Seq()))
nonTail(fun)(fId => transformFunArgs(args)(fId, Seq()))
}
def transformLetRec(funs: Seq[S.Fun], body: S.Tree) = {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment