diff -r 8160c55991b9 -r 0138618eff73 progs/fun/simple-cps.sc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/progs/fun/simple-cps.sc Tue May 30 13:27:54 2023 +0100 @@ -0,0 +1,63 @@ +// Source language: arithmetic expressions with function calls +enum Expr { + case Num(n: Int) + case Aop(op: String, e1: Expr, e2: Expr) + case Call(fname: String, args: List[Expr]) +} +import Expr._ + +// Target language +// "trivial" KValues +enum KVal { + case KVar(s: String) + case KNum(n: Int) + case KAop(op: String, v1: KVal, v2: KVal) + case KCall(fname: String, args: List[KVal]) +} +import KVal._ + +// KExpressions +enum KExp { + case KReturn(v: KVal) + case KLet(x: String, v: KVal, e: KExp) +} +import KExp._ + +var cnt = -1 +def Fresh(s: String) = { + cnt = cnt + 1 + s"${s}_${cnt}" +} + +def CPS(e: Expr)(k: KVal => KExp): KExp = e match { + case Num(i) => k(KNum(i)) + case Aop(op, l, r) => { + val z = Fresh("z") + CPS(l)(l => + CPS(r)(r => KLet(z, KAop(op, l, r), k(KVar(z))))) + } + case Call(fname, args) => { + def aux(args: List[Expr], vs: List[KVal]) : KExp = args match { + case Nil => { + val z = Fresh("tmp") + KLet(z, KCall(fname, vs), k(KVar(z))) + } + case a::as => CPS(a)(r => aux(as, vs ::: List(r))) + } + aux(args, Nil) + } +} + +def CPSi(e: Expr) : KExp = CPS(e)(KReturn(_)) + + +//1 + foo(bar(4 * -7), 3, id(12)) +val etest = + Aop("+", Num(1), + Call("foo", + List(Call("bar", + List(Aop("*", Num(4), Num(-7)))), + Num(3), + Call("id", List(Num(12)))))) + +println(CPSi(etest))