updated
authorChristian Urban <christian.urban@kcl.ac.uk>
Mon, 13 May 2024 00:34:09 +0100
changeset 651 e69c7e03bbd1
parent 650 516240b57cfb
child 652 1daec107e6ab
updated
SystemF-compiler.sc
bsc-projects.html
compiler.scala
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SystemF-compiler.sc	Mon May 13 00:34:09 2024 +0100
@@ -0,0 +1,818 @@
+/*
+
+Code in Scala for the paper
+
+  From System F to Typed Assembly Language
+  
+  by Morrisett, Walker, Crary and Glew
+  
+The interesting feature is that the compiler deals with closure conversions
+and hoisting of nested functions.
+
+It works with Scala 3 (scala-cli) by typing
+
+ $ scala-cli SystemF-compiler.sc 
+
+*/
+
+
+type Num = Int
+type Idn = String
+
+var counter = -1
+// for generating new variables
+
+def Fresh(x: Idn) = {
+  counter += 1
+  x ++ "_" ++ counter.toString()
+}
+
+def commas(s: List[String]) : String = s match {
+  case Nil => ""
+  case s::Nil => s
+  case s::ss => s + "," + commas(ss)
+}
+def cutlines(s: List[String]) : String = s match {
+  case Nil => ""
+  case s::ss => s + "\n" + cutlines(ss)
+}
+
+
+abstract class Prim
+case class PLUS() extends Prim { override def toString = "+" }
+case class MINUS() extends Prim { override def toString = "-" }
+case class MULT() extends Prim { override def toString = "*" }
+
+abstract class FTerm
+case class FVar(x : Idn) extends FTerm { override def toString = x }
+case class FNum(i : Num) extends FTerm { override def toString = i.toString }
+case class FFix(x : Idn, x1: Idn, e : FTerm) extends FTerm {
+  override def toString = s"fix $x ($x1).$e" 
+}
+case class FApp(e1 : FTerm, e2 : FTerm) extends FTerm {
+  override def toString = s"($e1) ($e2)"
+}
+case class FTuple(es : List[FTerm]) extends FTerm {
+  override def toString = s"<${commas(es.map(_.toString))}>"
+}
+case class FProj(i : Num, e : FTerm) extends FTerm {
+  override def toString = s"proj$i $e"
+}
+case class FPrimOp(e1 : FTerm, p : Prim, e2 : FTerm) extends FTerm {
+  override def toString = s"$e1 $p $e2"
+}
+case class FIf0(e1 : FTerm, e2 : FTerm, e3 : FTerm) extends FTerm {
+  override def toString = s"if0($e1, $e2, $e3)"
+}
+
+
+abstract class KTerm
+abstract class KVal
+
+case class KApp(v : KVal, vs : List[KVal]) extends KTerm {
+  override def toString = s"v(${commas(vs.map(_.toString))})" 
+}
+case class KIf0(v : KVal, e1 : KTerm, e2 : KTerm) extends KTerm {
+  override def toString = s"if0($v, $e1, $e2)"
+}
+case class KHalt(v : KVal) extends KTerm { override def toString = "halt " + v }
+case class KLet(x : Idn, v : KVal, e : KTerm) extends KTerm {
+  override def toString = s"let $x = $v in $e"
+}
+case class KLetProj(x : Idn, i : Num, v : KVal, e : KTerm) extends KTerm {
+  override def toString = s"let $x =$i $v in $e"
+}
+case class KLetPrimOp(x : Idn, v1 : KVal, p : Prim, v2 : KVal, e : KTerm) extends KTerm {
+  override def toString = s"let x = $v1 $p $v2 in $e"
+}
+
+
+case class KVVar(x : Idn) extends KVal { override def toString = x }
+case class KVNum(i : Num) extends KVal { override def toString = i.toString }
+case class KVTuple(vs : List[KVal]) extends KVal {
+  override def toString = s"<${commas(vs.map(_.toString))}>"
+}
+case class KVFix(x : Idn, args : List[Idn], e : KTerm) extends KVal {
+  override def toString = s"fix $x (${commas(args)}). $e"
+}
+
+// CPS tail translation
+def CPST(e: FTerm) : (KVal => KTerm) = e match {
+  case FVar(x) => (c: KVal) => KApp(c, List(KVVar(x))) 
+  case FNum(i) => (c: KVal) => KApp(c, List(KVNum(i))) 
+  case FIf0(e1, e2, e3) => (c: KVal) => {
+    val e1_prime = CPS(e1)
+    val e2_prime = CPST(e2)
+    val e3_prime = CPST(e3)
+    e1_prime((y: KVal) => KIf0(y, e2_prime(c), e3_prime(c)))
+  }
+  case FPrimOp(e1, op, e2) => (c: KVal) => {
+    val z = Fresh("z")
+    val e1_prime = CPS(e1)
+    val e2_prime = CPS(e2)
+    e1_prime((y1: KVal) => 
+      e2_prime((y2: KVal) => 
+        KLetPrimOp(z, y1, op, y2, KApp(c, List(KVVar(z))))))
+  }
+  case FFix(x, x1, e) => (c: KVal) => {
+    val c_prime = Fresh("c'")
+    val e_prime = CPST(e)
+    KApp(c, List(KVFix(x, List(x1, c_prime), e_prime(KVVar(c_prime)))))
+  }
+  case FApp(e1, e2) => (c: KVal) => {
+    val e1_prime = CPS(e1)
+    val e2_prime = CPS(e2)
+    e1_prime((y1: KVal) => 
+      e2_prime((y2: KVal) => 
+        KApp(y1, List(y2, c))))
+  }
+  case FTuple(es) => (c: KVal) => {
+    def aux(es: List[FTerm], vs: List[KVal]) : KTerm = es match {
+      case Nil => KApp(c, vs.reverse)
+      case (e::es) => CPS(e)((y: KVal) => aux(es, y::vs)) 
+    }
+    aux(es, Nil) 
+  }
+  case FProj(i, e) => (c: KVal) => {
+    val z = Fresh("z")
+    CPS(e)((y: KVal) => KLetProj(z, i, y, KApp(c, List(KVVar(z)))))
+  }
+}
+
+// CPS translation
+def CPS(e: FTerm) : (KVal => KTerm) => KTerm = e match {
+  case FVar(i) => (k: KVal => KTerm) => k(KVVar(i)) 
+  case FNum(i) => (k: KVal => KTerm) => k(KVNum(i)) 
+  case FFix(x, x1, e) => (k: KVal => KTerm) => {
+    val c = Fresh("c")
+    val e_prime = CPST(e)
+    k(KVFix(x, List(x1, c), e_prime(KVVar(c))))
+  }
+  case FApp(e1, e2) => (k: KVal => KTerm) => {
+    val fr = Fresh("")
+    val z = Fresh("z")
+    val e1_prime = CPS(e1)
+    val e2_prime = CPS(e2)
+    e1_prime((y1: KVal) => 
+      e2_prime((y2: KVal) =>
+        KApp(y1, List(y2, KVFix(fr, List(z), k(KVVar(z)))))))
+  }
+  case FIf0(e1, e2, e3) => (k: KVal => KTerm) => {
+    val fr = Fresh("")
+    val c = Fresh("c")
+    val z = Fresh("z")
+    val e1_prime = CPS(e1)
+    val e2_prime = CPST(e2)
+    val e3_prime = CPST(e3)
+    e1_prime((y: KVal) =>
+      KLet(c, KVFix(fr, List(z), k(KVVar(z))),  
+                KIf0(y, e2_prime(KVVar(c)), e3_prime(KVVar(c)))))
+  }
+  case FPrimOp(e1, op, e2) => (k: KVal => KTerm) => {
+    val z = Fresh("z")
+    val e1_prime = CPS(e1)
+    val e2_prime = CPS(e2)
+    e1_prime((y1: KVal) => e2_prime((y2: KVal) => KLetPrimOp(z, y1, op, y2, k(KVVar(z)))))
+  }
+  case FTuple(es) => (k: KVal => KTerm) => {
+    def aux(es: List[FTerm], vs: List[KVal]) : KTerm = es match {
+      case Nil => k(KVTuple(vs.reverse))
+      case (e::es) => CPS(e)((y: KVal) => aux(es, y::vs)) 
+    }
+    aux(es, Nil) 
+  }
+  case FProj(i, e) => (k: KVal => KTerm) => {
+    val z = Fresh("z")
+    CPS(e)((y: KVal) => KLetProj(z, i, y, k(KVVar(z))))
+  }
+}
+
+
+
+//free variable function
+def FVKval(v: KVal) : Set[Idn] = v match {
+  case KVVar(x) => Set(x)
+  case KVNum(i) => Set()
+  case KVTuple(vs) => vs.flatMap{FVKval}.toSet
+  case KVFix(x, args, e) => FVKexp(e) -- args - x 
+}
+
+def FVKexp(e: KTerm) : Set[Idn] = e match {
+  case KApp(v, vs) => FVKval(v) ++ vs.flatMap{FVKval}.toSet
+  case KIf0(v, e1, e2) => FVKval(v) ++ FVKexp(e1) ++ FVKexp(e2)
+  case KHalt(v) => FVKval(v)
+  case KLet(x, v, e) => FVKval(v) ++ (FVKexp(e) - x) 
+  case KLetProj(x, i, v, e) => FVKval(v) ++ (FVKexp(e) - x)
+  case KLetPrimOp(x, v1, p, v2, e) => (FVKexp(e) - x) ++ FVKval(v1) ++ FVKval(v2)
+}
+
+
+abstract class CTerm 
+abstract class CVal 
+
+case class CApp(v : CVal, vs : List[CVal]) extends CTerm  {
+  override def toString = s"$v(${commas(vs.map(_.toString))})"
+}
+case class CIf0(v : CVal, e1 : CTerm, e2 : CTerm) extends CTerm {
+  override def toString = s"if0($v, $e1, $e2)"
+}
+case class CHalt(v : CVal) extends CTerm { override def toString = "halt " + v }
+case class CLet(x : Idn, v : CVal, e : CTerm) extends CTerm {
+  override def toString = s"let $x = $v in\n$e"
+}
+case class CLetProj(x : Idn, i : Num, v : CVal, e : CTerm) extends CTerm {
+  override def toString = s"let $x =$i v in\n$e"
+}
+case class CLetPrimOp(x : Idn, v1 : CVal, p : Prim, v2 : CVal, e : CTerm) extends CTerm {
+  override def toString = s"let $x = $v1 $p $v2 in\n$e"
+}
+
+case class CVVar(x : Idn) extends CVal { override def toString = x }
+case class CVNum(i : Num) extends CVal { override def toString = i.toString }
+case class CVTuple(vs : List[CVal]) extends CVal {
+  override def toString = s"<${commas(vs.map(_.toString))}>"
+}
+case class CVFixCode(x : Idn, args : List[Idn], e : CTerm) extends CVal {
+  override def toString = s"fixcode $x(${commas(args)}).$e" 
+}
+
+
+
+// closure conversion
+def CExp(e: KTerm) : CTerm = e match {
+  case KApp(v, vs) => {
+    val z = Fresh("z")
+    val z_code = Fresh("zcode")
+    val z_env = Fresh("zenv")
+    CLet(z, CVal(v), 
+      CLetProj(z_code, 0, CVVar(z),
+        CLetProj(z_env, 1, CVVar(z),
+          CApp(CVVar(z_code), CVVar(z_env) :: vs.map{CVal}))))       
+  }
+  case KIf0(v, e1, e2) => CIf0(CVal(v), CExp(e1), CExp(e2))
+  case KHalt(v) => CHalt(CVal(v))
+  case KLet(x, v, e) => CLet(x, CVal(v), CExp(e))
+  case KLetProj(x, i, v, e) => CLetProj(x, i, CVal(v), CExp(e))
+  case KLetPrimOp(x, v1, p, v2, e) => CLetPrimOp(x, CVal(v1), p, CVal(v2), CExp(e))
+}
+
+def CVal(v: KVal) : CVal = v match {
+  case KVVar(x) => CVVar(x)
+  case KVNum(i) => CVNum(i)
+  case KVTuple(vs) => CVTuple(vs.map{CVal})
+  case KVFix(x, args, e) => {
+    val x_env = Fresh(x + ".env")
+    val ys = FVKval(KVFix(x, args, e)).toList
+    val ys_index = 
+      ys.zipWithIndex.foldRight(CExp(e)) {case ((x, n), e) => CLetProj(x, n, CVVar(x_env), e) } 
+    val v_code = CVFixCode(x, x_env :: args, ys_index)
+    val v_env = CVTuple(ys.map{CVVar(_)})
+    CVTuple(List(v_code, v_env))
+  }
+}
+
+abstract class HTerm
+abstract class HVal { 
+  def eval(env: Map[Idn, HVal]) : HVal
+}
+
+case class HApp(v : HVal, vs : List[HVal]) extends HTerm {
+  override def toString =  s"$v(${commas(vs.map(_.toString))})" 
+}
+case class HIf0(v : HVal, e1 : HTerm, e2 : HTerm) extends HTerm {
+  override def toString = s"if0($v, $e1, $e2)"
+}
+case class HHalt(v : HVal) extends HTerm { 
+  override def toString = s"halt $v" 
+}
+case class HLet(x : Idn, v : HVal, e : HTerm) extends HTerm {
+  override def toString = s"let $x = $v in\n$e"
+}
+case class HLetProj(x : Idn, i : Num, v : HVal, e : HTerm) extends HTerm {
+  override def toString = s"let $x =$i $v in\n$e"
+}
+case class HLetPrimOp(x : Idn, v1 : HVal, p : Prim, v2 : HVal, e : HTerm) extends HTerm {
+  override def toString = s"let $x = $v1 $p $v2 in\n$e"
+}
+
+case class HVVar(x : Idn) extends HVal { 
+  override def toString = x 
+  def eval(env: Map[Idn, HVal]) : HVal = env(x)
+}
+case class HVNum(i : Num) extends HVal { 
+  override def toString = i.toString 
+  def eval(env: Map[Idn, HVal]) : HVal = HVNum(i)
+}
+case class HVTuple(vs : List[HVal]) extends HVal {
+  override def toString = "<" + commas (vs.map(_.toString)) + ">"
+  def eval(env: Map[Idn, HVal]) : HVal = HVTuple(vs.map(_.eval(env)))
+}
+case class HVLabel(l: Idn) extends HVal { 
+  override def toString = l 
+  def eval(env: Map[Idn, HVal]) : HVal = HVLabel(l)
+}
+
+
+case class HBlock(args: List[Idn], term: HTerm) {
+  override def toString = "code(" + commas(args) + ").\n" + term + "\n"
+}
+
+case class HProg(blocks: Map[Idn, HBlock], term: HTerm) {
+  override def toString = "\nheap:\n" +
+    cutlines(blocks.toList.map(_ match { case (x, y) => x + " -> " + y.toString })) +
+      "in start:\n" + term.toString 
+
+  def run_block(pretty: Boolean, l: Idn, as: List[HVal], env: Map[Idn, HVal]) : Unit = {
+    val blk = blocks(l)
+    val env_prime = (blk.args zip as).toMap  
+    if (pretty) println("Referenced: " + l + " -> " + blk)
+    run(pretty, blk.term, env ++ env_prime)
+  }
+
+  def run(pretty: Boolean, e: HTerm, env: Map[Idn, HVal]) : Unit = {
+    if (pretty) println("Env:" + env.toList.length  + " stored values)\n" + 
+                        cutlines(env.toList.sortBy {_._1}.map(_.toString)))
+    if (pretty) println("Term:\n" + e.toString)
+    if (pretty) scala.io.StdIn.readLine()
+    e match {
+      case HHalt(v) => println ("Finished with result " + v.eval(env))
+      case HApp(v, vs) => (v.eval(env), vs.map(_.eval(env))) match {
+        case (HVLabel(l), vs) => run_block(pretty, l, vs, env)
+        case _ => throw new IllegalArgumentException("not a label")
+      }
+      case HLet(x, v, e) => run(pretty, e, env + (x -> v.eval(env)))
+      case HLetProj(x, i, v, e) => v.eval(env) match {
+        case HVTuple(vs) => run(pretty, e, env + (x -> vs(i)))
+        case _ => throw new IllegalArgumentException("not a tuple")
+      }
+      case HLetPrimOp(x, v1, p, v2, e) => (v1.eval(env), p, v2.eval(env)) match {
+        case (HVNum(m), PLUS(), HVNum(n)) =>  run(pretty, e, env + (x -> HVNum(m + n)))
+        case (HVNum(m), MINUS(), HVNum(n)) => run(pretty, e, env + (x -> HVNum(m - n)))
+        case (HVNum(m), MULT(), HVNum(n)) =>  run(pretty, e, env + (x -> HVNum(m * n)))
+        case _ => throw new IllegalArgumentException("not a number")
+      }
+      case HIf0(v, e1, e2) => v.eval(env) match {
+        case HVNum(0) => run(pretty, e1, env)
+        case _ => run(pretty, e2, env) 
+      }
+    }
+  }
+  
+  def run_prog(pretty: Boolean) = run(pretty, term, Map())
+}
+
+
+
+// hoisting
+def H(e: CTerm, ls: Map[Idn, HVal]) : (HTerm, Map[Idn, HBlock]) = e match {
+  case CApp(v, vs) => {
+    val (v_prime, hs) = HV(v, ls)
+    val (vs_prime, hss) = vs.map{HV(_, ls)}.unzip
+    (HApp(v_prime, vs_prime), hs ++ hss.flatten)
+  }
+  case CIf0(v, e1, e2) => {
+    val (v_prime, hs1) = HV(v, ls)
+    val (e1_prime, hs2) = H(e1, ls)
+    val (e2_prime, hs3) = H(e2, ls)
+    (HIf0(v_prime, e1_prime, e2_prime), hs1 ++ hs2 ++ hs3)
+  }
+  case CHalt(v) => {
+    val (v_prime, hs) = HV(v, ls) 
+    (HHalt(v_prime), hs)
+  }
+  case CLet(x, v, e) => {
+    val (v_prime, hs1) = HV(v, ls)
+    val (e_prime, hs2) = H(e, ls)
+    (HLet(x, v_prime, e_prime), hs1 ++ hs2)
+  }
+  case CLetProj(x, i, v, e) => {
+    val (v_prime, hs1) = HV(v, ls)
+    val (e_prime, hs2) = H(e, ls)
+    (HLetProj(x, i, v_prime, e_prime), hs1 ++ hs2)
+  }
+  case CLetPrimOp(x, v1, p, v2, e) => {
+    val (v1_prime, hs1) = HV(v1, ls)
+    val (v2_prime, hs2) = HV(v2, ls)
+    val (e_prime, hs3) = H(e, ls)
+    (HLetPrimOp(x, v1_prime, p, v2_prime, e_prime), hs1 ++ hs2 ++ hs3)
+  }
+}
+
+def HV(v: CVal, ls: Map[Idn, HVal]) : (HVal, Map[Idn, HBlock]) = v match {
+  case CVVar(x) => ls.get(x) match {
+    case Some(v) => (v, Map())
+    case None => (HVVar(x), Map())
+  }
+  case CVNum(i) => (HVNum(i), Map())
+  case CVTuple(vs) => {
+    val (vs_prime, hss) = vs.map{HV(_, ls)}.unzip
+    (HVTuple(vs_prime), hss.flatten.toMap)
+  }
+  case CVFixCode(x, args, e) => {
+    val l = Fresh(x + ".block")
+    val (e_prime, hs) = H(e, ls + (x -> HVTuple(List(HVLabel(l), HVVar(args.head)))))
+    (HVLabel(l), hs + (l -> HBlock(args, e_prime)))
+  } 
+}
+
+def HP(e: CTerm) = {
+  val (e_prime, hs) = H(e, Map())
+  HProg(hs, e_prime)
+}
+
+
+abstract class TALVal {
+  def eval(regs: Map[Idn, TALVal]) : TALVal
+}
+abstract class TALInstr {
+  def update_regs(regs: Map[Idn, TALVal]) :  Map[Idn, TALVal] = regs
+}
+
+case class TALReg(r: Idn) extends TALVal { 
+  override def toString = r 
+  def eval(regs: Map[Idn, TALVal]) = regs(r).eval(regs)
+}
+case class TALLabel(l: Idn) extends TALVal { 
+  override def toString = l 
+  def eval(regs: Map[Idn, TALVal]) = TALLabel(l)
+}
+case class TALNum(i: Int) extends TALVal { 
+  override def toString = i.toString 
+  def eval(regs: Map[Idn, TALVal]) = TALNum(i)
+}
+case class TALTuple(vs: List[TALVal]) extends TALVal {
+  override def toString = "<" + commas (vs.map(_.toString)) + ">"
+  def eval(regs: Map[Idn, TALVal]) = TALTuple(vs.map(_.eval(regs)))
+}
+
+
+case class TALAdd(r1: Idn, r2: Idn, v: TALVal) extends TALInstr {
+  override def toString = "Add " + r1 + " " + r2 + " " + v
+  override def update_regs (regs: Map[Idn, TALVal]) : Map[Idn, TALVal] = (regs(r2), v) match {
+    case (TALNum(n), TALNum(m)) => regs + (r1 -> TALNum(n + m))
+    case (TALNum(n), TALReg(r3)) => regs(r3) match { 
+      case TALNum(m) => regs + (r1 -> TALNum (n + m))
+      case _ => throw new IllegalArgumentException("not a number")
+    }
+    case _ => throw new IllegalArgumentException("not a number")
+  }
+}
+case class TALSub(r1: Idn, r2: Idn, v: TALVal) extends TALInstr {
+  override def toString = "Sub " + r1 + " " + r2 + " " + v
+  override def update_regs (regs: Map[Idn, TALVal]) : Map[Idn, TALVal] = (regs(r2), v) match {
+    case (TALNum(n), TALNum(m)) => regs + (r1 -> TALNum(n - m))
+    case (TALNum(n), TALReg(r3)) => regs(r3) match {
+      case TALNum(m) => regs + (r1 -> TALNum (n - m))
+      case _ => throw new IllegalArgumentException("not a number")
+    }
+    case _ => throw new IllegalArgumentException("not a number")
+  }
+}
+case class TALMul(r1: Idn, r2: Idn, v: TALVal) extends TALInstr {
+  override def toString = "Mul " + r1 + " " + r2 + " " + v
+  override def update_regs (regs: Map[Idn, TALVal]) : Map[Idn, TALVal] = (regs(r2), v) match {
+    case (TALNum(n), TALNum(m)) => regs + (r1 -> TALNum (n * m))
+    case (TALNum(n), TALReg(r3)) => regs(r3) match {
+      case TALNum(m) => regs + (r1 -> TALNum (n * m))
+      case _ => throw new IllegalArgumentException("not a number")
+    }
+    case _ => throw new IllegalArgumentException("not a number")
+  }
+}
+case class TALBnz(r: Idn, v: TALVal) extends TALInstr {
+  override def toString = "Bnz " + r + " " + v
+}
+case class TALMov(r: Idn, v: TALVal) extends TALInstr {
+  override def toString = "Mov " + r + " " + v
+  override def update_regs (regs: Map[Idn, TALVal]) : Map[Idn, TALVal] = v match {
+    case TALReg(r1) => regs + (r -> regs(r1)) 
+    case _ => regs + (r -> v)
+  }
+}
+case class TALProj(r1: Idn, r2: Idn, i: Num) extends TALInstr {
+  override def toString = "Ldi " + r1 + " <- " + r2 + "[" + i + "]" 
+  override def update_regs (regs: Map[Idn, TALVal]) : Map[Idn, TALVal] = { 
+    regs(r2) match {
+      case TALTuple(vs) => regs + (r1 -> vs(i)) 
+      case _ => throw new IllegalArgumentException("not a tuple: ")
+    }
+  }
+}
+
+case class TALJmp(v: TALVal) extends TALInstr {
+  override def toString = "Jmp " + v
+}
+case class TALHalt() extends TALInstr { 
+  override def toString = "halt" 
+}
+
+
+case class TALBlock(regs: List[Idn], cs: List[TALInstr]) {
+  override def toString = "code(" + commas(regs) + ").\n" + cutlines(cs.map{_.toString}) + "\n"
+}
+
+case class TALProg(blocks: Map[Idn, TALBlock], start: List[TALInstr]) {
+  override def toString =  "heap:\n" +
+    cutlines(blocks.toList.map(_ match { case (x, y) => x + " -> " + y.toString })) +
+      "start block:\n" + cutlines(start.map(_.toString)) 
+
+  def run_block(pretty: Boolean, l: Idn, regs: Map[Idn, TALVal]) : Unit = {
+    val blk = blocks(l)
+    if (pretty) println("Referenced: " + l + " -> " + blk)
+    val regs_prime = for ((r, n) <- blk.regs.zipWithIndex) yield (r, TALReg("RArg_" + n.toString).eval(regs))
+    run(pretty, blk.cs, regs ++ regs_prime.toMap)
+  }
+
+  def run(pretty: Boolean, cs: List[TALInstr], regs: Map[Idn, TALVal]) : Unit = {
+    if (pretty) println("Regs:(" + regs.toList.length  + " stored values)\n" + 
+                        cutlines(regs.toList.sortBy {_._1}.map(_.toString)))
+    if (pretty) println("Instrs:\n" + cutlines(cs.map(_.toString)))
+    if (pretty) scala.io.StdIn.readLine()
+    cs match {
+      case (TALHalt() :: _) => println ("Finished with result " + regs("RArg_0"))
+      case (TALJmp(TALLabel(l)) :: _) => run_block(pretty, l, regs)
+      case (TALJmp(TALReg(r)) :: _) => regs(r) match {
+        case TALLabel(l) => run_block(pretty, l, regs)
+        case _ => throw new IllegalArgumentException("jump to non-label")
+      }
+      case (TALBnz(r, TALLabel(l)) :: cs) => regs(r) match {
+        case TALNum(0) => run(pretty, cs, regs)
+        case _ => run_block(pretty, l, regs) 
+      }
+      case (c :: cs) => run(pretty, cs, c.update_regs(regs))
+      case Nil => throw new IllegalArgumentException("no instruction left")
+    }
+  } 
+
+  def run_prog(pretty: Boolean) : Unit = run(pretty, start, Map())
+}
+
+def mk_vreg(s: String) = "Reg_" + s
+def mk_areg(i: Int) = "RArg_" + i.toString
+  
+
+def Tval(v: HVal) : TALVal = v match {
+  case HVVar(x) => TALReg("Reg_" + x)
+  case HVNum(i) => TALNum(i)
+  case HVTuple(vs) => TALTuple(vs.map(Tval)) 
+  case HVLabel(l) => TALLabel(l)
+}
+
+def Texp(e: HTerm) : (Map[Idn, TALBlock], List[TALInstr]) = e match {
+  case HApp(v, vs) => {
+    val fr_reg0 = Fresh("r0") 
+    val fr_regs = vs.map((v) => Fresh("r"))
+    val movs0 = List(TALMov(fr_reg0, Tval(v)))
+    val movs1 = for ((r, v) <- (fr_regs zip vs)) yield TALMov(r, Tval(v))
+    val movs2 = for ((r, i) <- fr_regs.zipWithIndex) yield TALMov(mk_areg(i), TALReg(r))
+    val movs3 = List(TALJmp(TALReg(fr_reg0))) 
+    (Map(), movs0 ::: movs1 ::: movs2 ::: movs3)
+  }
+  case HIf0(v, e1, e2) => {
+    val l = Fresh("else_branch")
+    val r = Fresh("r")
+    val (h1, comp1) = Texp(e1)
+    val (h2, comp2) = Texp(e2)
+    val code = List(TALMov(r, Tval(v)), TALBnz(r, TALLabel(l)))
+    val h3 = TALBlock(Nil, comp2)
+    (h1 ++ h2 + (l -> h3), code ::: comp1)
+  }
+  case HHalt(v) => {
+    (Map(), List(TALMov(mk_areg(0), Tval(v)), TALHalt()))
+  }
+  case HLet(x, v, e) => {
+    val (h, comp) = Texp(e)
+    val code = TALMov(mk_vreg(x), Tval(v))
+    (h, code :: comp)
+  }
+  case HLetPrimOp(x, v1, PLUS(), v2, e) => {
+    val r = mk_vreg(x)
+    val (h, comp) = Texp(e)
+    val code = List(TALMov(r, Tval(v1)), TALAdd(r, r, Tval(v2)))
+    (h, code ::: comp)
+  }
+  case HLetPrimOp(x, v1, MINUS(), v2, e) => {
+    val r = mk_vreg(x)
+    val (h, comp) = Texp(e)
+    val code = List(TALMov(r, Tval(v1)), TALSub(r, r, Tval(v2)))
+    (h, code ::: comp)
+  }
+  case HLetPrimOp(x, v1, MULT(), v2, e) => {
+    val r = mk_vreg(x)
+    val (h, comp) = Texp(e)
+    val code = List(TALMov(r, Tval(v1)), TALMul(r, r, Tval(v2)))
+    (h, code ::: comp)
+  }  
+  case HLetProj(x, i, v, e) => {
+    val r = mk_vreg(x)
+    val (h, comp) = Texp(e)
+    val code = List(TALMov(r, Tval(v)), TALProj(r, r, i))
+    (h, code ::: comp)
+  }
+}
+
+def Tblock(l: Idn, hb: HBlock) : List[(Idn, TALBlock)] = hb match {  
+  case HBlock(args, e) => {
+    val (h, comp) = Texp(e)
+    (l, TALBlock(args.map("Reg_" + _), comp)) :: h.toList
+  }
+}
+
+def Tprog(prog: HProg) = prog match {
+  case HProg(heaps, e) => {
+    val (hs, comp) = Texp(e)
+    val heap_prime = for ((l, hb) <- heaps) yield Tblock(l, hb)
+    TALProg(hs ++ heap_prime.flatten.toMap, comp)
+  }
+}
+
+/* Simple examples
+
+// tuple <1,2,3>
+val prog0 = FTuple(List(FNum(1), FNum(2), FNum(3)))
+val Kresult0 = CPS(prog0)((y:KVal) => KHalt(y))
+val Cresult0 = CExp(Kresult0)
+val Hresult0 = HP(Cresult0)
+val Tresult0 = Tprog(Hresult0)
+
+println("tuple example: \n")
+println("F: " + prog0.toString)
+println("K: " + Kresult0.toString)
+println("C: " + Cresult0.toString)
+println("H: " + Hresult0.toString)
+println("T: " + Tresult0.toString + "\n")
+Tresult0.run_prog(true)
+scala.io.StdIn.readLine()
+
+// tuple Proj 1 <1,2,3>
+val prog1 = FProj(1, FTuple(List(FNum(1), FNum(2), FNum(3))))
+val Kresult1 = CPS(prog1)((y:KVal) => KHalt(y))
+val Cresult1 = CExp(Kresult1)
+val Hresult1 = HP(Cresult1)
+val Tresult1 = Tprog(Hresult1)
+
+println("tuple - proj: \n")
+println("F: " + prog1.toString)
+println("K: " + Kresult1.toString)
+println("C: " + Cresult1.toString)
+println("H: " + Hresult1.toString)
+println("T: " + Tresult1.toString + "\n")
+Tresult1.run_prog(true)
+scala.io.StdIn.readLine()
+
+// 3 + 4
+val prog2 = FPrimOp(FNum(3),PLUS(),FNum(4))
+val Kresult2 = CPS(prog2)((y:KVal) => KHalt(y))
+val Cresult2 = CExp(Kresult2)
+val Hresult2 = HP(Cresult2)
+val Tresult2 = Tprog(Hresult2)
+
+println("3 + 4: \n")
+println("F: " + prog2.toString)
+println("K: " + Kresult2.toString)
+println("C: " + Cresult2.toString)
+println("H: " + Hresult2.toString)
+println("T: " + Tresult2.toString + "\n")
+Tresult2.run_prog(true)
+scala.io.StdIn.readLine()
+
+// (fix f(x). 18 * x + 32) 24
+val d1 = FPrimOp(FPrimOp(FNum(18), MULT(), FVar("x")), PLUS(), FNum(32))
+val prog3 = FApp(FFix("f", "x", d1), FNum(24))
+val Kresult3 = CPS(prog3)((y:KVal) => KHalt(y))
+val Cresult3 = CExp(Kresult3)
+val Hresult3 = HP(Cresult3)
+val Tresult3 = Tprog(Hresult3)
+
+println("(fix f(x). 18 * x + 32) 24 \n")
+println("F: " + prog3.toString + "\n")
+println("K: " + Kresult3.toString + "\n")
+println("C: " + Cresult3.toString + "\n")
+println("H: " + Hresult3.toString + "\n")
+Hresult3.run_prog(true)
+scala.io.StdIn.readLine()
+println("T: " + Tresult3.toString + "\n")
+Tresult3.run_prog(true)
+scala.io.StdIn.readLine()
+*/
+
+
+/*
+// twice-apply example
+// fix twice(f)._(x). f (f x)
+val fun = FFix("id", "x", FPrimOp(FVar("x"), MULT(), FVar("x")))
+val ffx = FApp(FVar("f"), FApp(FVar("f"), FVar("x")))
+val f1 = FFix("twice", "f", FFix("twicef", "x", ffx))
+val prog4 = FApp(FApp(f1, fun), FNum(2))
+val Kresult4 = CPS(prog4)((y:KVal) => KHalt(y))
+val Cresult4 = CExp(Kresult4)
+val Hresult4 = HP(Cresult4)
+val Tresult4 = Tprog(Hresult4)
+
+println("twice fun 2\n")
+println("F: " + prog4.toString + "\n")
+println("K: " + Kresult4.toString + "\n")
+println("C: " + Cresult4.toString + "\n")
+println("H: " + Hresult4.toString + "\n")
+//Hresult4.run_prog(false)
+//scala.io.StdIn.readLine()
+println("T: " + Tresult4.toString + "\n")
+Tresult4.run_prog(false)
+scala.io.StdIn.readLine()
+*/
+
+/*
+//identity function
+//fix id(x). x
+val id = FFix("id", "x", FVar("x"))
+val id_three = FApp(id, FNum(3))
+
+val Kresult5 = CPS(id_three)((y:KVal) => KHalt(y))
+val Cresult5 = CExp(Kresult5)
+val Hresult5 = HP(Cresult5)
+val Tresult5 = Tprog(Hresult5)
+
+println("id 3:")
+println("F: " + id_three.toString)
+println("K: " + Kresult5.toString + "\n")
+println("C: " + Cresult5.toString + "\n")
+println("H: " + Hresult5.toString + "\n")
+println("T: " + Tresult5.toString + "\n")
+Tresult5.run_prog(false)
+scala.io.StdIn.readLine()
+*/
+
+/*
+//example: factorial
+val f = FVar("f")
+val n = FVar("n")
+val one = FNum(1)
+val six = FNum(15)
+val e0 = FPrimOp(n, MINUS(), one)
+val e1 = FApp(f, e0)
+val e2 = FPrimOp(n, MULT(), e1)
+val fact: FTerm = FFix("f", "n", FIf0(n, one, e2))
+val fact_six = FApp(fact, six)
+
+
+val Kresult6 = CPS(fact_six)((y:KVal) => KHalt(y))
+val Cresult6 = CExp(Kresult6)
+val Hresult6 = HP(Cresult6)
+val Tresult6 = Tprog(Hresult6)
+
+println("fact 6: \n")
+println("F: " + fact_six)
+scala.io.StdIn.readLine()
+println("K: " + Kresult6.toString + "\n")
+scala.io.StdIn.readLine()
+println("C: " + Cresult6.toString + "\n")
+scala.io.StdIn.readLine()
+println("H: " + Hresult6.toString + "\n")
+println("-----------------------------")
+println("Execution")
+Hresult6.run_prog(false)
+scala.io.StdIn.readLine()
+println("T: " + Tresult6.toString + "\n")
+println("-----------------------------")
+println("Execution")
+Tresult6.run_prog(false)
+scala.io.StdIn.readLine()
+*/
+
+
+//example: fibonacci
+// fib(n).if0(n, 1,if0(n - 1, 1, fib(n - 1) + fib(n - 2))) 
+val fib = FVar("fib")
+val n = FVar("n")
+val one = FNum(1)
+val two = FNum(2)
+val minus_one = FPrimOp(n, MINUS(), one)
+val minus_two = FPrimOp(n, MINUS(), two)
+val fibonacci = 
+          FFix("fib", "n",
+            FIf0(n, one,
+              FIf0(minus_one, one, FPrimOp(FApp(fib, minus_one), PLUS(), FApp(fib, minus_two)))))
+val fib_apply = FApp(fibonacci, FNum(4))
+
+val Kresult7 = CPS(fib_apply)((y:KVal) => KHalt(y))
+val Cresult7 = CExp(Kresult7)
+val Hresult7 = HP(Cresult7)
+val Tresult7 = Tprog(Hresult7)
+
+println("fib: \n")
+println("F: " + fib_apply)
+scala.io.StdIn.readLine()
+println("K: " + Kresult7.toString + "\n")
+scala.io.StdIn.readLine()
+println("C: " + Cresult7.toString + "\n")
+scala.io.StdIn.readLine()
+println("H: " + Hresult7.toString + "\n")
+println("-----------------------------")
+println("H Prog")
+Hresult7.run_prog(false)
+scala.io.StdIn.readLine()
+println("T: " + Tresult7.toString + "\n")
+println("-----------------------------")
+println("TAL")
+Tresult7.run_prog(false)
+scala.io.StdIn.readLine()
--- a/bsc-projects.html	Wed May 08 15:22:31 2024 +0100
+++ b/bsc-projects.html	Mon May 13 00:34:09 2024 +0100
@@ -1,12 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HEAD>
-<TITLE>2018/19 BSc Projects</TITLE>
+<TITLE>BSc Projects</TITLE>
 <BASE HREF="https://nms.kcl.ac.uk/christian.urban/">
 <script type="text/javascript" src="striper.js"></script>
 <link rel="stylesheet" href="nominal.css">
 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML">
 </script>
+<style>
+.note {
+  font-size: 100%;
+  color: "#4169E1" ;
+}
+</style>
 </HEAD>
 <BODY TEXT="#000000" 
       BGCOLOR="#4169E1" 
@@ -42,7 +48,7 @@
 </H4>
 
 <H4>In 2013/14, I was nominated by the students
-    for the best BSc project supervisor and best MSc project supervisor awards in the NMS
+    for the best BSc project supervisor and best MSc project supervisor awards in the NMES
     faculty. Somehow I won both. In 2014/15 I was nominated again for the best MSc
     project supervisor, but did not win it. ;o)
 </H4>  
@@ -169,7 +175,7 @@
   module, that would obviously give you a head-start with this project.
   </p>
 
-<li> <H4>[CU2] Grammars and Derivative-Based Parsing Algorithms</H4>
+<li> <H4>[CU1a] Grammars and Derivative-Based Parsing Algorithms</H4>
 
 <p>
 Parsing is an old nut. Generations of software developers need to do parsing of data or text.
@@ -200,22 +206,24 @@
 </p>
 
 
-<li> <H4>[CU3] A Compiler for a small Programming Language</H4>
+<li> <H4>[CU2] A Compiler for a small Programming Language</H4>
 
   <p>
   <b>Description:</b> 
   Compilers translate high-level programs that humans can read and write into
   efficient machine code that can be run on a CPU or virtual machine.
-  A compiler for a simple functional language generating X86 code is described
-  <A HREF="https://libraries.io/github/chameco/Shade">here</A>.
+  A compiler for a simple functional language generating assembly code is described
+  <A HREF="https://esumii.github.io/min-caml/paper.pdf">here</A>.
   I recently implemented a very simple compiler for an even simpler functional
   programming language following this 
   <A HREF="https://www.cs.princeton.edu/~dpw/papers/tal-toplas.pdf">paper</A> 
   (also described <A HREF="https://www.cs.princeton.edu/~dpw/papers/tal-tr.pdf">here</A>).
-  My code, written in <A HREF="http://www.scala-lang.org/">Scala</A>, of this compiler is 
-  <A HREF="https://nms.kcl.ac.uk/christian.urban/compiler.scala">here</A>.
-  The compiler can deal with simple programs involving natural numbers, such
-  as Fibonacci numbers or factorial (but it can be easily extended - that is not the point).
+  My code, written in <A HREF="http://www.scala-lang.org/">Scala</A>, for this compiler is 
+  <A HREF="https://nms.kcl.ac.uk/christian.urban/SystemF-compiler.scala">here</A>.
+  The compiler can only deal with simple programs involving natural numbers, such
+  as Fibonacci numbers or factorial function (but it can be easily extended - that is not the point).
+  The interesting feature in this compiler is that it can also deal with closure conversions and hoisting of
+  nested functions. 
   </p>
 
   <p>
@@ -223,11 +231,11 @@
   my compiler only produces some idealised machine code. For example I
   assume there are infinitely many registers. The goal of this
   project is to generate machine code that is more realistic and can
-  run on a CPU, like X86, or run on a virtual machine, say the JVM. 
+  run on a CPU, like X86, or run on a virtual machine, say the JVM.
+  You could also compile to the LLVM-IR.
   This gives probably a speedup of thousand times in comparison to
-  my naive machine code and virtual machine. The project
-  requires to dig into the literature about real CPUs and generating 
-  real machine code. 
+  my naive machine code and tiny virtual machine. The project
+  requires to dig into the literature about real  machine code. 
   </p>
   <p>
   An alternative is to not generate machine code, but build a compiler that compiles to
@@ -240,13 +248,13 @@
   very optimised subsets of JavaScript that can be used for this purpose:
   one is <A HREF="http://asmjs.org">asm.js</A> and the other is
   <A HREF="https://github.com/kripken/emscripten/wiki">emscripten</A>. Since
-  last year there is even the official <A HREF="http://webassembly.org">Webassembly</A>
+  a few year ago there is even the official <A HREF="http://webassembly.org">Webassembly</A>
   There is a <A HREF="http://kripken.github.io/emscripten-site/docs/getting_started/Tutorial.html">tutorial</A> for emscripten
   and an impressive <A HREF="https://youtu.be/c2uNDlP4RiE">demo</A> which runs the
   <A HREF="http://en.wikipedia.org/wiki/Unreal_Engine">Unreal Engine 3</A>
   in a browser with spectacular speed. This was achieved by compiling the
   C-code of the Unreal Engine to the LLVM intermediate language and then translating the LLVM
-  code to JavaScript.
+  code to JavaScript/Webassembly.
   </p>
 
   <p>
@@ -271,7 +279,8 @@
   what machine code looks like you can compile your C-program using gcc -S.
   </p>
   <p>
-  If JavaScript is chosen as a target instead, then there are plenty of <A HREF="http://www.w3schools.com/js/">tutorials</A> on the Web.
+    If JavaScript is chosen as a target instead, then there are plenty of
+    <A HREF="http://www.w3schools.com/js/">tutorials</A> on the Web.
   <A HREF="http://jsbooks.revolunet.com">Here</A> is a list of free books on JavaScript.
   A project from which you can draw inspiration is this
   <A HREF="http://jlongster.com/Outlet--My-Lisp-to-Javascript-Experiment">Lisp-to-JavaScript</A>
@@ -297,10 +306,18 @@
 
   <p>
   <B>PS:</B> Compiler projects consistently received high marks in the past.
-  I have supervised eight so far and most of them received a mark above 70% - one even was awarded a prize.
+  I have supervised eight so far and many of them received a mark above 70% - one even was awarded a prize.
+  However in order to achieve anything better than a passing mark, you need to go beyond the
+  compiler presented in the CFL-module. For example you could implement
+
+  <ol class="note">
+    <li>first-class functions and closure conversions</li>
+    <li>recursive datatypes</li>
+    <li>interesting type-systems</li>
+  </ol>
   </p>
 
-<li> <H4>[CU4] Webassembly Interpreter / Compiler</H4>
+<li> <H4>[CU2a] Webassembly Interpreter / Compiler</H4>
 
 <p>
 Webassembly is a recently agreed standard for speeding up web applications in browsers. In this 
@@ -319,6 +336,7 @@
 <B>Skills:</B> See [CU1].
 </p>
 
+<!--
 <li> <H4>[CU5] Slide-Making in the Web-Age</H4>
 
   <p>
@@ -629,7 +647,6 @@
 </ul>
 
 
-
 <li> <H4>Earlier Projects</H4>
 
  I am also open to project suggestions from you. You might find some inspiration from my earlier projects:
@@ -646,6 +663,7 @@
  <A HREF="https://nms.kcl.ac.uk/christian.urban/bsc-projects-17.html">BSc 2017/18</A>,
  <A HREF="https://nms.kcl.ac.uk/christian.urban/msc-projects-17.html">MSc 2017/18</A>,
  <A HREF="https://nms.kcl.ac.uk/christian.urban/bsc-projects-17.html">BSc 2018/19</A>
+-->
 </ul>
 </TD>
 </TR>  
--- a/compiler.scala	Wed May 08 15:22:31 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,801 +0,0 @@
-
-type Num = Int
-type Idn = String
-
-var counter = -1
-// for generating new variables
-
-def Fresh(x: Idn) = {
-  counter += 1
-  x ++ "_" ++ counter.toString()
-}
-
-def commas(s: List[String]) : String = s match {
-  case Nil => ""
-  case s::Nil => s
-  case s::ss => s + "," + commas(ss)
-}
-def cutlines(s: List[String]) : String = s match {
-  case Nil => ""
-  case s::ss => s + "\n" + cutlines(ss)
-}
-
-
-abstract class Prim
-case class PLUS() extends Prim { override def toString = " + " }
-case class MINUS() extends Prim { override def toString = " - " }
-case class MULT() extends Prim { override def toString = " * " }
-
-abstract class FTerm
-case class FVar(x : Idn) extends FTerm { override def toString = x }
-case class FNum(i : Num) extends FTerm { override def toString = i.toString }
-case class FFix(x : Idn, x1: Idn, e : FTerm) extends FTerm {
-  override def toString = "fix " + x + "(" + x1 + ")" + "." + e 
-}
-case class FApp(e1 : FTerm, e2 : FTerm) extends FTerm {
-  override def toString = "(" + e1 + ") (" + e2 + ")"
-}
-case class FTuple(es : List[FTerm]) extends FTerm {
-  override def toString = "<" + commas(es.map(_.toString)) + ">"
-}
-case class FProj(i : Num, e : FTerm) extends FTerm {
-  override def toString = "proj " + i.toString + " " + e
-}
-case class FPrimOp(e1 : FTerm, p : Prim, e2 : FTerm) extends FTerm {
-  override def toString = e1 + p.toString + e2
-}
-case class FIf0(e1 : FTerm, e2 : FTerm, e3 : FTerm) extends FTerm {
-  override def toString = "if0(" + e1 + "," + e2 + "," + e3 + ")"
-}
-
-
-abstract class KTerm
-abstract class KVal
-
-case class KApp(v : KVal, vs : List[KVal]) extends KTerm {
-  override def toString = v + "(" + commas(vs.map(_.toString)) + ")" 
-}
-case class KIf0(v : KVal, e1 : KTerm, e2 : KTerm) extends KTerm {
-  override def toString = "if0(" + v + "," + e1 + "," + e2 + ")"
-}
-case class KHalt(v : KVal) extends KTerm { override def toString = "halt " + v }
-case class KLet(x : Idn, v : KVal, e : KTerm) extends KTerm {
-  override def toString = "let " + x + " = " + v + " in " + e
-}
-case class KLetProj(x : Idn, i : Num, v : KVal, e : KTerm) extends KTerm {
-  override def toString = "let " + x + " =" + i + " " + v + " in " + e
-}
-case class KLetPrimOp(x : Idn, v1 : KVal, p : Prim, v2 : KVal, e : KTerm) extends KTerm {
-  override def toString = "let " + x + " = " + v1 + p + v2 + " in " + e
-}
-
-
-case class KVVar(x : Idn) extends KVal { override def toString = x }
-case class KVNum(i : Num) extends KVal { override def toString = i.toString }
-case class KVTuple(vs : List[KVal]) extends KVal {
-  override def toString = "<" + commas(vs.map(_.toString)) + ">"
-}
-case class KVFix(x : Idn, args : List[Idn], e : KTerm) extends KVal {
-  override def toString = "fix " + x + "(" + commas(args) + ")." + e
-}
-
-// CPS tail translation
-def CPST(e: FTerm) : (KVal => KTerm) = e match {
-  case FVar(x) => (c: KVal) => KApp(c, List(KVVar(x))) 
-  case FNum(i) => (c: KVal) => KApp(c, List(KVNum(i))) 
-  case FIf0(e1, e2, e3) => (c: KVal) => {
-    val e1_prime = CPS(e1)
-    val e2_prime = CPST(e2)
-    val e3_prime = CPST(e3)
-    e1_prime((y: KVal) => KIf0(y, e2_prime(c), e3_prime(c)))
-  }
-  case FPrimOp(e1, op, e2) => (c: KVal) => {
-    val z = Fresh("z")
-    val e1_prime = CPS(e1)
-    val e2_prime = CPS(e2)
-    e1_prime((y1: KVal) => 
-      e2_prime((y2: KVal) => 
-        KLetPrimOp(z, y1, op, y2, KApp(c, List(KVVar(z))))))
-  }
-  case FFix(x, x1, e) => (c: KVal) => {
-    val c_prime = Fresh("c'")
-    val e_prime = CPST(e)
-    KApp(c, List(KVFix(x, List(x1, c_prime), e_prime(KVVar(c_prime)))))
-  }
-  case FApp(e1, e2) => (c: KVal) => {
-    val e1_prime = CPS(e1)
-    val e2_prime = CPS(e2)
-    e1_prime((y1: KVal) => 
-      e2_prime((y2: KVal) => 
-        KApp(y1, List(y2, c))))
-  }
-  case FTuple(es) => (c: KVal) => {
-    def aux(es: List[FTerm], vs: List[KVal]) : KTerm = es match {
-      case Nil => KApp(c, vs.reverse)
-      case (e::es) => CPS(e)((y: KVal) => aux(es, y::vs)) 
-    }
-    aux(es, Nil) 
-  }
-  case FProj(i, e) => (c: KVal) => {
-    val z = Fresh("z")
-    CPS(e)((y: KVal) => KLetProj(z, i, y, KApp(c, List(KVVar(z)))))
-  }
-}
-
-// CPS translation
-def CPS(e: FTerm) : (KVal => KTerm) => KTerm = e match {
-  case FVar(i) => (k: KVal => KTerm) => k(KVVar(i)) 
-  case FNum(i) => (k: KVal => KTerm) => k(KVNum(i)) 
-  case FFix(x, x1, e) => (k: KVal => KTerm) => {
-    val c = Fresh("c")
-    val e_prime = CPST(e)
-    k(KVFix(x, List(x1, c), e_prime(KVVar(c))))
-  }
-  case FApp(e1, e2) => (k: KVal => KTerm) => {
-    val fr = Fresh("")
-    val z = Fresh("z")
-    val e1_prime = CPS(e1)
-    val e2_prime = CPS(e2)
-    e1_prime((y1: KVal) => 
-      e2_prime((y2: KVal) =>
-        KApp(y1, List(y2, KVFix(fr, List(z), k(KVVar(z)))))))
-  }
-  case FIf0(e1, e2, e3) => (k: KVal => KTerm) => {
-    val fr = Fresh("")
-    val c = Fresh("c")
-    val z = Fresh("z")
-    val e1_prime = CPS(e1)
-    val e2_prime = CPST(e2)
-    val e3_prime = CPST(e3)
-    e1_prime((y: KVal) =>
-      KLet(c, KVFix(fr, List(z), k(KVVar(z))),  
-                KIf0(y, e2_prime(KVVar(c)), e3_prime(KVVar(c)))))
-  }
-  case FPrimOp(e1, op, e2) => (k: KVal => KTerm) => {
-    val z = Fresh("z")
-    val e1_prime = CPS(e1)
-    val e2_prime = CPS(e2)
-    e1_prime((y1: KVal) => e2_prime((y2: KVal) => KLetPrimOp(z, y1, op, y2, k(KVVar(z)))))
-  }
-  case FTuple(es) => (k: KVal => KTerm) => {
-    def aux(es: List[FTerm], vs: List[KVal]) : KTerm = es match {
-      case Nil => k(KVTuple(vs.reverse))
-      case (e::es) => CPS(e)((y: KVal) => aux(es, y::vs)) 
-    }
-    aux(es, Nil) 
-  }
-  case FProj(i, e) => (k: KVal => KTerm) => {
-    val z = Fresh("z")
-    CPS(e)((y: KVal) => KLetProj(z, i, y, k(KVVar(z))))
-  }
-}
-
-
-
-//free variable function
-def FVKval(v: KVal) : Set[Idn] = v match {
-  case KVVar(x) => Set(x)
-  case KVNum(i) => Set()
-  case KVTuple(vs) => vs.flatMap{FVKval}.toSet
-  case KVFix(x, args, e) => FVKexp(e) -- args - x 
-}
-
-def FVKexp(e: KTerm) : Set[Idn] = e match {
-  case KApp(v, vs) => FVKval(v) ++ vs.flatMap{FVKval}.toSet
-  case KIf0(v, e1, e2) => FVKval(v) ++ FVKexp(e1) ++ FVKexp(e2)
-  case KHalt(v) => FVKval(v)
-  case KLet(x, v, e) => FVKval(v) ++ (FVKexp(e) - x) 
-  case KLetProj(x, i, v, e) => FVKval(v) ++ (FVKexp(e) - x)
-  case KLetPrimOp(x, v1, p, v2, e) => (FVKexp(e) - x) ++ FVKval(v1) ++ FVKval(v2)
-}
-
-
-abstract class CTerm 
-abstract class CVal 
-
-case class CApp(v : CVal, vs : List[CVal]) extends CTerm  {
-  override def toString = v + "(" + commas(vs.map(_.toString)) + ")"
-}
-case class CIf0(v : CVal, e1 : CTerm, e2 : CTerm) extends CTerm {
-  override def toString = "if0(" + v + "," + e1 + "," + e2 + ")"
-}
-case class CHalt(v : CVal) extends CTerm { override def toString = "halt " + v }
-case class CLet(x : Idn, v : CVal, e : CTerm) extends CTerm {
-  override def toString = "let " + x + " = " + v + " in\n" + e
-}
-case class CLetProj(x : Idn, i : Num, v : CVal, e : CTerm) extends CTerm {
-  override def toString = "let " + x + " =" + i + " " + v + " in\n" + e
-}
-case class CLetPrimOp(x : Idn, v1 : CVal, p : Prim, v2 : CVal, e : CTerm) extends CTerm {
-  override def toString = "let " + x + " =" + v1 + p + v2 + " in\n" + e
-}
-
-case class CVVar(x : Idn) extends CVal { override def toString = x }
-case class CVNum(i : Num) extends CVal { override def toString = i.toString }
-case class CVTuple(vs : List[CVal]) extends CVal {
-  override def toString = "<" + commas(vs.map(_.toString)) + ">"
-}
-case class CVFixCode(x : Idn, args : List[Idn], e : CTerm) extends CVal {
-  override def toString = "fixcode " + x + "(" + commas(args) + ")." + e 
-}
-
-
-
-// closure conversion
-def CExp(e: KTerm) : CTerm = e match {
-  case KApp(v, vs) => {
-    val z = Fresh("z")
-    val z_code = Fresh("zcode")
-    val z_env = Fresh("zenv")
-    CLet(z, CVal(v), 
-      CLetProj(z_code, 0, CVVar(z),
-        CLetProj(z_env, 1, CVVar(z),
-          CApp(CVVar(z_code), CVVar(z_env) :: vs.map{CVal}))))       
-  }
-  case KIf0(v, e1, e2) => CIf0(CVal(v), CExp(e1), CExp(e2))
-  case KHalt(v) => CHalt(CVal(v))
-  case KLet(x, v, e) => CLet(x, CVal(v), CExp(e))
-  case KLetProj(x, i, v, e) => CLetProj(x, i, CVal(v), CExp(e))
-  case KLetPrimOp(x, v1, p, v2, e) => CLetPrimOp(x, CVal(v1), p, CVal(v2), CExp(e))
-}
-
-def CVal(v: KVal) : CVal = v match {
-  case KVVar(x) => CVVar(x)
-  case KVNum(i) => CVNum(i)
-  case KVTuple(vs) => CVTuple(vs.map{CVal})
-  case KVFix(x, args, e) => {
-    val x_env = Fresh(x + ".env")
-    val ys = FVKval(KVFix(x, args, e)).toList
-    val ys_index = 
-      ys.zipWithIndex.foldRight(CExp(e)) {case ((x, n), e) => CLetProj(x, n, CVVar(x_env), e) } 
-    val v_code = CVFixCode(x, x_env :: args, ys_index)
-    val v_env = CVTuple(ys.map{CVVar(_)})
-    CVTuple(List(v_code, v_env))
-  }
-}
-
-abstract class HTerm
-abstract class HVal { 
-  def eval(env: Map[Idn, HVal]) : HVal
-}
-
-case class HApp(v : HVal, vs : List[HVal]) extends HTerm {
-  override def toString =  v + "(" + commas (vs.map(_.toString)) + ")" 
-}
-case class HIf0(v : HVal, e1 : HTerm, e2 : HTerm) extends HTerm {
-  override def toString = "if0(" + v + "," + e1 + "," + e2 + ")"
-}
-case class HHalt(v : HVal) extends HTerm { 
-  override def toString = "halt " + v 
-}
-case class HLet(x : Idn, v : HVal, e : HTerm) extends HTerm {
-  override def toString = "let " + x + " = " + v + " in\n" + e
-}
-case class HLetProj(x : Idn, i : Num, v : HVal, e : HTerm) extends HTerm {
-  override def toString = "let " + x + " =" + i + " " + v + " in\n" + e
-}
-case class HLetPrimOp(x : Idn, v1 : HVal, p : Prim, v2 : HVal, e : HTerm) extends HTerm {
-  override def toString = "let " + x + " = " + v1 + p + v2 + " in\n" + e
-}
-
-case class HVVar(x : Idn) extends HVal { 
-  override def toString = x 
-  def eval(env: Map[Idn, HVal]) : HVal = env(x)
-}
-case class HVNum(i : Num) extends HVal { 
-  override def toString = i.toString 
-  def eval(env: Map[Idn, HVal]) : HVal = HVNum(i)
-}
-case class HVTuple(vs : List[HVal]) extends HVal {
-  override def toString = "<" + commas (vs.map(_.toString)) + ">"
-  def eval(env: Map[Idn, HVal]) : HVal = HVTuple(vs.map(_.eval(env)))
-}
-case class HVLabel(l: Idn) extends HVal { 
-  override def toString = l 
-  def eval(env: Map[Idn, HVal]) : HVal = HVLabel(l)
-}
-
-
-case class HBlock(args: List[Idn], term: HTerm) {
-  override def toString = "code(" + commas(args) + ").\n" + term + "\n"
-}
-
-case class HProg(blocks: Map[Idn, HBlock], term: HTerm) {
-  override def toString = "\nheap:\n" +
-    cutlines(blocks.toList.map(_ match { case (x, y) => x + " -> " + y.toString })) +
-      "in start:\n" + term.toString 
-
-  def run_block(pretty: Boolean, l: Idn, as: List[HVal], env: Map[Idn, HVal]) : Unit = {
-    val blk = blocks(l)
-    val env_prime = (blk.args zip as).toMap  
-    if (pretty) println("Referenced: " + l + " -> " + blk)
-    run(pretty, blk.term, env ++ env_prime)
-  }
-
-  def run(pretty: Boolean, e: HTerm, env: Map[Idn, HVal]) : Unit = {
-    if (pretty) println("Env:" + env.toList.length  + " stored values)\n" + 
-                        cutlines(env.toList.sortBy {_._1}.map(_.toString)))
-    if (pretty) println("Term:\n" + e.toString)
-    if (pretty) Console.readLine
-    e match {
-      case HHalt(v) => println ("Finished with result " + v.eval(env))
-      case HApp(v, vs) => (v.eval(env), vs.map(_.eval(env))) match {
-        case (HVLabel(l), vs) => run_block(pretty, l, vs, env)
-        case _ => throw new IllegalArgumentException("not a label")
-      }
-      case HLet(x, v, e) => run(pretty, e, env + (x -> v.eval(env)))
-      case HLetProj(x, i, v, e) => v.eval(env) match {
-        case HVTuple(vs) => run(pretty, e, env + (x -> vs(i)))
-        case _ => throw new IllegalArgumentException("not a tuple")
-      }
-      case HLetPrimOp(x, v1, p, v2, e) => (v1.eval(env), p, v2.eval(env)) match {
-        case (HVNum(m), PLUS(), HVNum(n)) =>  run(pretty, e, env + (x -> HVNum(m + n)))
-        case (HVNum(m), MINUS(), HVNum(n)) => run(pretty, e, env + (x -> HVNum(m - n)))
-        case (HVNum(m), MULT(), HVNum(n)) =>  run(pretty, e, env + (x -> HVNum(m * n)))
-        case _ => throw new IllegalArgumentException("not a number")
-      }
-      case HIf0(v, e1, e2) => v.eval(env) match {
-        case HVNum(0) => run(pretty, e1, env)
-        case _ => run(pretty, e2, env) 
-      }
-    }
-  }
-  
-  def run_prog(pretty: Boolean) = run(pretty, term, Map())
-}
-
-
-
-// hoisting
-def H(e: CTerm, ls: Map[Idn, HVal]) : (HTerm, Map[Idn, HBlock]) = e match {
-  case CApp(v, vs) => {
-    val (v_prime, hs) = HV(v, ls)
-    val (vs_prime, hss) = vs.map{HV(_, ls)}.unzip
-    (HApp(v_prime, vs_prime), hs ++ hss.flatten)
-  }
-  case CIf0(v, e1, e2) => {
-    val (v_prime, hs1) = HV(v, ls)
-    val (e1_prime, hs2) = H(e1, ls)
-    val (e2_prime, hs3) = H(e2, ls)
-    (HIf0(v_prime, e1_prime, e2_prime), hs1 ++ hs2 ++ hs3)
-  }
-  case CHalt(v) => {
-    val (v_prime, hs) = HV(v, ls) 
-    (HHalt(v_prime), hs)
-  }
-  case CLet(x, v, e) => {
-    val (v_prime, hs1) = HV(v, ls)
-    val (e_prime, hs2) = H(e, ls)
-    (HLet(x, v_prime, e_prime), hs1 ++ hs2)
-  }
-  case CLetProj(x, i, v, e) => {
-    val (v_prime, hs1) = HV(v, ls)
-    val (e_prime, hs2) = H(e, ls)
-    (HLetProj(x, i, v_prime, e_prime), hs1 ++ hs2)
-  }
-  case CLetPrimOp(x, v1, p, v2, e) => {
-    val (v1_prime, hs1) = HV(v1, ls)
-    val (v2_prime, hs2) = HV(v2, ls)
-    val (e_prime, hs3) = H(e, ls)
-    (HLetPrimOp(x, v1_prime, p, v2_prime, e_prime), hs1 ++ hs2 ++ hs3)
-  }
-}
-
-def HV(v: CVal, ls: Map[Idn, HVal]) : (HVal, Map[Idn, HBlock]) = v match {
-  case CVVar(x) => ls.get(x) match {
-    case Some(v) => (v, Map())
-    case None => (HVVar(x), Map())
-  }
-  case CVNum(i) => (HVNum(i), Map())
-  case CVTuple(vs) => {
-    val (vs_prime, hss) = vs.map{HV(_, ls)}.unzip
-    (HVTuple(vs_prime), hss.flatten.toMap)
-  }
-  case CVFixCode(x, args, e) => {
-    val l = Fresh(x + ".block")
-    val (e_prime, hs) = H(e, ls + (x -> HVTuple(List(HVLabel(l), HVVar(args.head)))))
-    (HVLabel(l), hs + (l -> HBlock(args, e_prime)))
-  } 
-}
-
-def HP(e: CTerm) = {
-  val (e_prime, hs) = H(e, Map())
-  HProg(hs, e_prime)
-}
-
-
-abstract class TALVal {
-  def eval(regs: Map[Idn, TALVal]) : TALVal
-}
-abstract class TALInstr {
-  def update_regs(regs: Map[Idn, TALVal]) :  Map[Idn, TALVal] = regs
-}
-
-case class TALReg(r: Idn) extends TALVal { 
-  override def toString = r 
-  def eval(regs: Map[Idn, TALVal]) = regs(r).eval(regs)
-}
-case class TALLabel(l: Idn) extends TALVal { 
-  override def toString = l 
-  def eval(regs: Map[Idn, TALVal]) = TALLabel(l)
-}
-case class TALNum(i: Int) extends TALVal { 
-  override def toString = i.toString 
-  def eval(regs: Map[Idn, TALVal]) = TALNum(i)
-}
-case class TALTuple(vs: List[TALVal]) extends TALVal {
-  override def toString = "<" + commas (vs.map(_.toString)) + ">"
-  def eval(regs: Map[Idn, TALVal]) = TALTuple(vs.map(_.eval(regs)))
-}
-
-
-case class TALAdd(r1: Idn, r2: Idn, v: TALVal) extends TALInstr {
-  override def toString = "Add " + r1 + " " + r2 + " " + v
-  override def update_regs (regs: Map[Idn, TALVal]) : Map[Idn, TALVal] = (regs(r2), v) match {
-    case (TALNum(n), TALNum(m)) => regs + (r1 -> TALNum(n + m))
-    case (TALNum(n), TALReg(r3)) => regs(r3) match { 
-      case TALNum(m) => regs + (r1 -> TALNum (n + m))
-      case _ => throw new IllegalArgumentException("not a number")
-    }
-    case _ => throw new IllegalArgumentException("not a number")
-  }
-}
-case class TALSub(r1: Idn, r2: Idn, v: TALVal) extends TALInstr {
-  override def toString = "Sub " + r1 + " " + r2 + " " + v
-  override def update_regs (regs: Map[Idn, TALVal]) : Map[Idn, TALVal] = (regs(r2), v) match {
-    case (TALNum(n), TALNum(m)) => regs + (r1 -> TALNum(n - m))
-    case (TALNum(n), TALReg(r3)) => regs(r3) match {
-      case TALNum(m) => regs + (r1 -> TALNum (n - m))
-      case _ => throw new IllegalArgumentException("not a number")
-    }
-    case _ => throw new IllegalArgumentException("not a number")
-  }
-}
-case class TALMul(r1: Idn, r2: Idn, v: TALVal) extends TALInstr {
-  override def toString = "Mul " + r1 + " " + r2 + " " + v
-  override def update_regs (regs: Map[Idn, TALVal]) : Map[Idn, TALVal] = (regs(r2), v) match {
-    case (TALNum(n), TALNum(m)) => regs + (r1 -> TALNum (n * m))
-    case (TALNum(n), TALReg(r3)) => regs(r3) match {
-      case TALNum(m) => regs + (r1 -> TALNum (n * m))
-      case _ => throw new IllegalArgumentException("not a number")
-    }
-    case _ => throw new IllegalArgumentException("not a number")
-  }
-}
-case class TALBnz(r: Idn, v: TALVal) extends TALInstr {
-  override def toString = "Bnz " + r + " " + v
-}
-case class TALMov(r: Idn, v: TALVal) extends TALInstr {
-  override def toString = "Mov " + r + " " + v
-  override def update_regs (regs: Map[Idn, TALVal]) : Map[Idn, TALVal] = v match {
-    case TALReg(r1) => regs + (r -> regs(r1)) 
-    case _ => regs + (r -> v)
-  }
-}
-case class TALProj(r1: Idn, r2: Idn, i: Num) extends TALInstr {
-  override def toString = "Ldi " + r1 + " <- " + r2 + "[" + i + "]" 
-  override def update_regs (regs: Map[Idn, TALVal]) : Map[Idn, TALVal] = { 
-    regs(r2) match {
-      case TALTuple(vs) => regs + (r1 -> vs(i)) 
-      case _ => throw new IllegalArgumentException("not a tuple: ")
-    }
-  }
-}
-
-case class TALJmp(v: TALVal) extends TALInstr {
-  override def toString = "Jmp " + v
-}
-case class TALHalt() extends TALInstr { 
-  override def toString = "halt" 
-}
-
-
-case class TALBlock(regs: List[Idn], cs: List[TALInstr]) {
-  override def toString = "code(" + commas(regs) + ").\n" + cutlines(cs.map{_.toString}) + "\n"
-}
-
-case class TALProg(blocks: Map[Idn, TALBlock], start: List[TALInstr]) {
-  override def toString =  "heap:\n" +
-    cutlines(blocks.toList.map(_ match { case (x, y) => x + " -> " + y.toString })) +
-      "start block:\n" + cutlines(start.map(_.toString)) 
-
-  def run_block(pretty: Boolean, l: Idn, regs: Map[Idn, TALVal]) : Unit = {
-    val blk = blocks(l)
-    if (pretty) println("Referenced: " + l + " -> " + blk)
-    val regs_prime = for ((r, n) <- blk.regs.zipWithIndex) yield (r, TALReg("RArg_" + n.toString).eval(regs))
-    run(pretty, blk.cs, regs ++ regs_prime.toMap)
-  }
-
-  def run(pretty: Boolean, cs: List[TALInstr], regs: Map[Idn, TALVal]) : Unit = {
-    if (pretty) println("Regs:(" + regs.toList.length  + " stored values)\n" + 
-                        cutlines(regs.toList.sortBy {_._1}.map(_.toString)))
-    if (pretty) println("Instrs:\n" + cutlines(cs.map(_.toString)))
-    if (pretty) Console.readLine
-    cs match {
-      case (TALHalt() :: _) => println ("Finished with result " + regs("RArg_0"))
-      case (TALJmp(TALLabel(l)) :: _) => run_block(pretty, l, regs)
-      case (TALJmp(TALReg(r)) :: _) => regs(r) match {
-        case TALLabel(l) => run_block(pretty, l, regs)
-        case _ => throw new IllegalArgumentException("jump to non-label")
-      }
-      case (TALBnz(r, TALLabel(l)) :: cs) => regs(r) match {
-        case TALNum(0) => run(pretty, cs, regs)
-        case _ => run_block(pretty, l, regs) 
-      }
-      case (c :: cs) => run(pretty, cs, c.update_regs(regs))
-      case Nil => throw new IllegalArgumentException("no instruction left")
-    }
-  } 
-
-  def run_prog(pretty: Boolean) : Unit = run(pretty, start, Map())
-}
-
-def mk_vreg(s: String) = "Reg_" + s
-def mk_areg(i: Int) = "RArg_" + i.toString
-  
-
-def Tval(v: HVal) : TALVal = v match {
-  case HVVar(x) => TALReg("Reg_" + x)
-  case HVNum(i) => TALNum(i)
-  case HVTuple(vs) => TALTuple(vs.map(Tval)) 
-  case HVLabel(l) => TALLabel(l)
-}
-
-def Texp(e: HTerm) : (Map[Idn, TALBlock], List[TALInstr]) = e match {
-  case HApp(v, vs) => {
-    val fr_reg0 = Fresh("r0") 
-    val fr_regs = vs.map((v) => Fresh("r"))
-    val movs0 = List(TALMov(fr_reg0, Tval(v)))
-    val movs1 = for ((r, v) <- (fr_regs zip vs)) yield TALMov(r, Tval(v))
-    val movs2 = for ((r, i) <- fr_regs.zipWithIndex) yield TALMov(mk_areg(i), TALReg(r))
-    val movs3 = List(TALJmp(TALReg(fr_reg0))) 
-    (Map(), movs0 ::: movs1 ::: movs2 ::: movs3)
-  }
-  case HIf0(v, e1, e2) => {
-    val l = Fresh("else_branch")
-    val r = Fresh("r")
-    val (h1, comp1) = Texp(e1)
-    val (h2, comp2) = Texp(e2)
-    val code = List(TALMov(r, Tval(v)), TALBnz(r, TALLabel(l)))
-    val h3 = TALBlock(Nil, comp2)
-    (h1 ++ h2 + (l -> h3), code ::: comp1)
-  }
-  case HHalt(v) => {
-    (Map(), List(TALMov(mk_areg(0), Tval(v)), TALHalt()))
-  }
-  case HLet(x, v, e) => {
-    val (h, comp) = Texp(e)
-    val code = TALMov(mk_vreg(x), Tval(v))
-    (h, code :: comp)
-  }
-  case HLetPrimOp(x, v1, PLUS(), v2, e) => {
-    val r = mk_vreg(x)
-    val (h, comp) = Texp(e)
-    val code = List(TALMov(r, Tval(v1)), TALAdd(r, r, Tval(v2)))
-    (h, code ::: comp)
-  }
-  case HLetPrimOp(x, v1, MINUS(), v2, e) => {
-    val r = mk_vreg(x)
-    val (h, comp) = Texp(e)
-    val code = List(TALMov(r, Tval(v1)), TALSub(r, r, Tval(v2)))
-    (h, code ::: comp)
-  }
-  case HLetPrimOp(x, v1, MULT(), v2, e) => {
-    val r = mk_vreg(x)
-    val (h, comp) = Texp(e)
-    val code = List(TALMov(r, Tval(v1)), TALMul(r, r, Tval(v2)))
-    (h, code ::: comp)
-  }  
-  case HLetProj(x, i, v, e) => {
-    val r = mk_vreg(x)
-    val (h, comp) = Texp(e)
-    val code = List(TALMov(r, Tval(v)), TALProj(r, r, i))
-    (h, code ::: comp)
-  }
-}
-
-def Tblock(l: Idn, hb: HBlock) : List[(Idn, TALBlock)] = hb match {  
-  case HBlock(args, e) => {
-    val (h, comp) = Texp(e)
-    (l, TALBlock(args.map("Reg_" + _), comp)) :: h.toList
-  }
-}
-
-def Tprog(prog: HProg) = prog match {
-  case HProg(heaps, e) => {
-    val (hs, comp) = Texp(e)
-    val heap_prime = for ((l, hb) <- heaps) yield Tblock(l, hb)
-    TALProg(hs ++ heap_prime.flatten.toMap, comp)
-  }
-}
-
-/* Simple examples
-
-// tuple <1,2,3>
-val prog0 = FTuple(List(FNum(1), FNum(2), FNum(3)))
-val Kresult0 = CPS(prog0)((y:KVal) => KHalt(y))
-val Cresult0 = CExp(Kresult0)
-val Hresult0 = HP(Cresult0)
-val Tresult0 = Tprog(Hresult0)
-
-println("tuple example: \n")
-println("F: " + prog0.toString)
-println("K: " + Kresult0.toString)
-println("C: " + Cresult0.toString)
-println("H: " + Hresult0.toString)
-println("T: " + Tresult0.toString + "\n")
-Tresult0.run_prog(true)
-Console.readLine
-
-// tuple Proj 1 <1,2,3>
-val prog1 = FProj(1, FTuple(List(FNum(1), FNum(2), FNum(3))))
-val Kresult1 = CPS(prog1)((y:KVal) => KHalt(y))
-val Cresult1 = CExp(Kresult1)
-val Hresult1 = HP(Cresult1)
-val Tresult1 = Tprog(Hresult1)
-
-println("tuple - proj: \n")
-println("F: " + prog1.toString)
-println("K: " + Kresult1.toString)
-println("C: " + Cresult1.toString)
-println("H: " + Hresult1.toString)
-println("T: " + Tresult1.toString + "\n")
-Tresult1.run_prog(true)
-Console.readLine
-
-// 3 + 4
-val prog2 = FPrimOp(FNum(3),PLUS(),FNum(4))
-val Kresult2 = CPS(prog2)((y:KVal) => KHalt(y))
-val Cresult2 = CExp(Kresult2)
-val Hresult2 = HP(Cresult2)
-val Tresult2 = Tprog(Hresult2)
-
-println("3 + 4: \n")
-println("F: " + prog2.toString)
-println("K: " + Kresult2.toString)
-println("C: " + Cresult2.toString)
-println("H: " + Hresult2.toString)
-println("T: " + Tresult2.toString + "\n")
-Tresult2.run_prog(true)
-Console.readLine
-
-// (fix f(x). 18 * x + 32) 24
-val d1 = FPrimOp(FPrimOp(FNum(18), MULT(), FVar("x")), PLUS(), FNum(32))
-val prog3 = FApp(FFix("f", "x", d1), FNum(24))
-val Kresult3 = CPS(prog3)((y:KVal) => KHalt(y))
-val Cresult3 = CExp(Kresult3)
-val Hresult3 = HP(Cresult3)
-val Tresult3 = Tprog(Hresult3)
-
-println("(fix f(x). 18 * x + 32) 24 \n")
-println("F: " + prog3.toString + "\n")
-println("K: " + Kresult3.toString + "\n")
-println("C: " + Cresult3.toString + "\n")
-println("H: " + Hresult3.toString + "\n")
-Hresult3.run_prog(true)
-Console.readLine
-println("T: " + Tresult3.toString + "\n")
-Tresult3.run_prog(true)
-Console.readLine
-*/
-
-
-/*
-// twice-apply example
-// fix twice(f)._(x). f (f x)
-val fun = FFix("id", "x", FPrimOp(FVar("x"), MULT(), FVar("x")))
-val ffx = FApp(FVar("f"), FApp(FVar("f"), FVar("x")))
-val f1 = FFix("twice", "f", FFix("twicef", "x", ffx))
-val prog4 = FApp(FApp(f1, fun), FNum(2))
-val Kresult4 = CPS(prog4)((y:KVal) => KHalt(y))
-val Cresult4 = CExp(Kresult4)
-val Hresult4 = HP(Cresult4)
-val Tresult4 = Tprog(Hresult4)
-
-println("twice fun 2\n")
-println("F: " + prog4.toString + "\n")
-println("K: " + Kresult4.toString + "\n")
-println("C: " + Cresult4.toString + "\n")
-println("H: " + Hresult4.toString + "\n")
-//Hresult4.run_prog(false)
-//Console.readLine
-println("T: " + Tresult4.toString + "\n")
-Tresult4.run_prog(false)
-Console.readLine
-*/
-
-/*
-//identity function
-//fix id(x). x
-val id = FFix("id", "x", FVar("x"))
-val id_three = FApp(id, FNum(3))
-
-val Kresult5 = CPS(id_three)((y:KVal) => KHalt(y))
-val Cresult5 = CExp(Kresult5)
-val Hresult5 = HP(Cresult5)
-val Tresult5 = Tprog(Hresult5)
-
-println("id 3:")
-println("F: " + id_three.toString)
-println("K: " + Kresult5.toString + "\n")
-println("C: " + Cresult5.toString + "\n")
-println("H: " + Hresult5.toString + "\n")
-println("T: " + Tresult5.toString + "\n")
-Tresult5.run_prog(false)
-Console.readLine
-*/
-
-/*
-//example: factorial
-val f = FVar("f")
-val n = FVar("n")
-val one = FNum(1)
-val six = FNum(15)
-val e0 = FPrimOp(n, MINUS(), one)
-val e1 = FApp(f, e0)
-val e2 = FPrimOp(n, MULT(), e1)
-val fact: FTerm = FFix("f", "n", FIf0(n, one, e2))
-val fact_six = FApp(fact, six)
-
-
-val Kresult6 = CPS(fact_six)((y:KVal) => KHalt(y))
-val Cresult6 = CExp(Kresult6)
-val Hresult6 = HP(Cresult6)
-val Tresult6 = Tprog(Hresult6)
-
-println("fact 6: \n")
-println("F: " + fact_six)
-Console.readLine
-println("K: " + Kresult6.toString + "\n")
-Console.readLine
-println("C: " + Cresult6.toString + "\n")
-Console.readLine
-println("H: " + Hresult6.toString + "\n")
-println("-----------------------------")
-println("Execution")
-Hresult6.run_prog(false)
-Console.readLine
-println("T: " + Tresult6.toString + "\n")
-println("-----------------------------")
-println("Execution")
-Tresult6.run_prog(false)
-Console.readLine
-*/
-
-
-//example: fibonacci
-// fib(n).if0(n, 1,if0(n - 1, 1, fib(n - 1) + fib(n - 2))) 
-val fib = FVar("fib")
-val n = FVar("n")
-val one = FNum(1)
-val two = FNum(2)
-val minus_one = FPrimOp(n, MINUS(), one)
-val minus_two = FPrimOp(n, MINUS(), two)
-val fibonacci = 
-          FFix("fib", "n",
-            FIf0(n, one,
-              FIf0(minus_one, one, FPrimOp(FApp(fib, minus_one), PLUS(), FApp(fib, minus_two)))))
-val fib_apply = FApp(fibonacci, FNum(4))
-
-val Kresult7 = CPS(fib_apply)((y:KVal) => KHalt(y))
-val Cresult7 = CExp(Kresult7)
-val Hresult7 = HP(Cresult7)
-val Tresult7 = Tprog(Hresult7)
-
-println("fib: \n")
-println("F: " + fib_apply)
-Console.readLine
-println("K: " + Kresult7.toString + "\n")
-Console.readLine
-println("C: " + Cresult7.toString + "\n")
-Console.readLine
-println("H: " + Hresult7.toString + "\n")
-println("-----------------------------")
-println("H Prog")
-Hresult7.run_prog(false)
-Console.readLine
-println("T: " + Tresult7.toString + "\n")
-println("-----------------------------")
-println("TAL")
-Tresult7.run_prog(false)
-Console.readLine