progs/fun_llvm.scala
changeset 653 9d7843934d30
parent 650 3031e3379ea3
child 654 fb6192488b91
equal deleted inserted replaced
652:4642e2073808 653:9d7843934d30
    54 
    54 
    55 
    55 
    56 
    56 
    57 // Abstract syntax trees for the Fun language
    57 // Abstract syntax trees for the Fun language
    58 abstract class KExp
    58 abstract class KExp
    59 
    59 abstract class KVal
    60 case class KVar(s: String) extends KExp
    60 
    61 case class KNum(i: Int) extends KExp
    61 case class KVar(s: String) extends KVal
    62 case class KAop(o: String, x1: String, x2: String) extends KExp
    62 case class KNum(i: Int) extends KVal
    63 case class KIfeq(x1: String, x2: String, e1: KExp, e2: KExp) extends KExp {
    63 case class KAop(o: String, v1: KVal, v2: KVal) extends KVal
    64   override def toString = s"KIf $x1 == $x2 \nIF\n$e1\nELSE\n$e2"
    64 case class KBop(o: String, v1: KVal, v2: KVal) extends KVal
    65 
    65 case class KCall(o: String, vrs: List[KVal]) extends KVal
    66 }
    66 
    67 case class KCall(o: String, vrs: List[String]) extends KExp
    67 case class KIf(x1: String, e1: KExp, e2: KExp) extends KExp {
    68 case class KLet(x: String, e1: KExp, e2: KExp) extends KExp {
    68   override def toString = s"KIf $x1\nIF\n$e1\nELSE\n$e2"
       
    69 }
       
    70 case class KLet(x: String, e1: KVal, e2: KExp) extends KExp {
    69   override def toString = s"let $x = $e1 in \n$e2" 
    71   override def toString = s"let $x = $e1 in \n$e2" 
    70 }
    72 }
    71 
    73 case class KReturn(v: KVal) extends KExp
    72 def K(e: Exp) : KExp = e match {
    74 
    73   case Var(s) => KVar(s) 
    75 def CPS(e: Exp)(k: KVal => KExp) : KExp = e match {
    74   case Num(i) => KNum(i)
    76   case Var(s) => k(KVar(s)) 
    75   case Aop(o, a1, a2) => {
    77   case Num(i) => k(KNum(i))
    76     val x1 = Fresh("tmp")
    78   case Aop(o, e1, e2) => {
    77     val x2 = Fresh("tmp") 
    79     val z = Fresh("tmp")
    78     KLet(x1, K(a1), KLet(x2, K(a2), KAop(o, x1, x2)))
    80     CPS(e1)(y1 => 
    79   } 
    81       CPS(e2)(y2 => KLet(z, KAop(o, y1, y2), k(KVar(z)))))
    80   case Call(name: String, args: List[Exp]) => {
    82   }
    81     val args_new = args.map{a => (Fresh("tmp"), K(a))}
    83   case If(Bop(o, b1, b2), e1, e2) => {
    82     def aux(as: List[(String, KExp)]) : KExp = as match {
    84     val z = Fresh("tmp")
    83       case Nil => KCall(name, args_new.map(_._1))
    85     CPS(b1)(y1 => 
    84       case (x, a)::rest => KLet(x, a, aux(rest))
    86       CPS(b2)(y2 => KLet(z, KBop(o, y1, y2), KIf(z, CPS(e1)(k), CPS(e2)(k)))))
       
    87   }
       
    88   case Call(name, args) => {
       
    89     def aux(args: List[Exp], vs: List[KVal]) : KExp = args match {
       
    90       case Nil => {
       
    91           val z = Fresh("tmp")
       
    92           KLet(z, KCall(name, vs), k(KVar(z)))
       
    93       }
       
    94       case e::es => CPS(e)(y => aux(es, vs ::: List(y)))
    85     }
    95     }
    86     aux(args_new)
    96     aux(args, Nil)
    87   }
    97   }
    88   case If(Bop("==", b1, b2), e1, e2) => {
    98   case Sequence(e1, e2) => {
    89     val x1 = Fresh("tmp")
    99     val z = Fresh("tmp")
    90     val x2 = Fresh("tmp") 
   100     CPS(e1)(y1 => 
    91     KLet(x1, K(b1), KLet(x2, K(b2), KIfeq(x1, x2, K(e1), K(e2))))
   101       CPS(e2)(y2 => KLet("_", y1, KLet(z, y2, k(KVar(z))))))
    92   }
   102   }
    93 }
   103 }   
    94 
   104 
    95 def Denest(e: KExp) : KExp = e match {
   105 def CPSi(e: Exp) = CPS(e)(KReturn)
    96   case KLet(xt, e1, e2) => {
   106 
    97     def insert(e: KExp) : KExp = e match {
   107 val e1 = Aop("*", Var("a"), Num(3))
    98       case KLet(yt, e3, e4) => KLet(yt, e3, insert(e4))
   108 CPS(e1)(KReturn)
    99       case e => KLet(xt, e, Denest(e2))
   109 
   100     }
   110 val e2 = Aop("+", Aop("*", Var("a"), Num(3)), Num(4))
   101     insert(Denest(e1))  
   111 CPS(e2)(KReturn)
   102   }
   112 
   103   case KIfeq(x1, x2, e1, e2) =>  KIfeq(x1, x2, Denest(e1), Denest(e2))
   113 val e3 = Aop("+", Num(2), Aop("*", Var("a"), Num(3)))
   104   case _ => e
   114 CPS(e3)(KReturn)
   105 }
   115 
   106 
   116 val e4 = Aop("+", Aop("-", Num(1), Num(2)), Aop("*", Var("a"), Num(3)))
       
   117 CPS(e4)(KReturn)
       
   118 
       
   119 val e5 = If(Bop("==", Num(1), Num(1)), Num(3), Num(4))
       
   120 CPS(e5)(KReturn)
       
   121 
       
   122 val e6 = If(Bop("!=", Num(10), Num(10)), e5, Num(40))
       
   123 CPS(e6)(KReturn)
       
   124 
       
   125 val e7 = Call("foo", List(Num(3)))
       
   126 CPS(e7)(KReturn)
       
   127 
       
   128 val e8 = Call("foo", List(Num(3), Num(4), Aop("+", Num(5), Num(6))))
       
   129 CPS(e8)(KReturn)
       
   130 
       
   131 val e9 = Sequence(Aop("*", Var("a"), Num(3)), Aop("+", Var("b"), Num(6)))
       
   132 CPS(e9)(KReturn)
   107 
   133 
   108 val e = Aop("*", Aop("+", Num(1), Call("foo", List(Var("a"), Num(3)))), Num(4))
   134 val e = Aop("*", Aop("+", Num(1), Call("foo", List(Var("a"), Num(3)))), Num(4))
   109 println(K(e))
   135 CPS(e)(KReturn)
   110 println()
   136 
   111 println(Denest(K(e)))
       
   112 println()
       
   113 
   137 
   114 
   138 
   115 
   139 
   116 // convenient string interpolations 
   140 // convenient string interpolations 
   117 // for instructions, labels and methods
   141 // for instructions, labels and methods
   122     def i(args: Any*): String = "   " ++ sc.s(args:_*) ++ "\n"
   146     def i(args: Any*): String = "   " ++ sc.s(args:_*) ++ "\n"
   123     def l(args: Any*): String = sc.s(args:_*) ++ ":\n"
   147     def l(args: Any*): String = sc.s(args:_*) ++ ":\n"
   124     def m(args: Any*): String = sc.s(args:_*) ++ "\n"
   148     def m(args: Any*): String = sc.s(args:_*) ++ "\n"
   125 }
   149 }
   126 
   150 
   127 
   151 def compile_op(op: String) = op match {
   128 type Env = Map[String, Int]
   152   case "+" => "add i32 "
   129 
   153   case "*" => "mul i32 "
   130 
   154   case "-" => "sub i32 "
       
   155   case "==" => "icmp eq i32 "
       
   156 }
       
   157 
       
   158 def compile_val(v: KVal) : String = v match {
       
   159   case KNum(i) => s"$i"
       
   160   case KVar(s) => s"%$s"
       
   161   case KAop(op, x1, x2) => 
       
   162     s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}"
       
   163   case KBop(op, x1, x2) => 
       
   164     s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}"
       
   165   case KCall(x1, args) => 
       
   166     s"call i32 @$x1 (${args.map(compile_val).mkString("i32 ", ", i32 ", "")})"
       
   167 }
   131 
   168 
   132 // compile K expressions
   169 // compile K expressions
   133 def compile_exp(a: KExp) : String = a match {
   170 def compile_exp(a: KExp) : String = a match {
   134   case KNum(i) => s"?$i?"
   171   case KReturn(v) =>
   135   case KVar(s) => s"?$s?"
   172     i"ret i32 ${compile_val(v)}"
   136   case KAop("+", x1, x2) => s"add i32 %$x1, i32 %$x2"
   173   case KLet(x: String, v: KVal, e: KExp) => 
   137   case KAop("-", x1, x2) => s"sub i32 %$x1, i32 %$x2"
   174     i"%$x = ${compile_val(v)}" ++ compile_exp(e)
   138   case KAop("*", x1, x2) => s"mul i32 %$x1, i32 %$x2"
   175   case KIf(x, e1, e2) => {
   139   case KLet(x: String, e1: KExp, e2: KExp) => {
       
   140     val is1 = compile_exp(e1)
       
   141     val is2 = compile_exp(e2)
       
   142     i"%$x = $is1" ++ is2
       
   143   }
       
   144   case KLet(x: String, e1: KExp, e2: KExp) => {
       
   145     val is1 = compile_exp(e1)
       
   146     val is2 = compile_exp(e2)
       
   147     i"%$x = $is1" ++ is2
       
   148   }
       
   149   case KIfeq(x1, x2, a1, a2) => {
       
   150     val if_br = Fresh("if_br")
   176     val if_br = Fresh("if_br")
   151     val else_br = Fresh("else_br")
   177     val else_br = Fresh("else_br")
   152     val x = Fresh("tmp")
       
   153     i"%$x = icmp eq i32 %$x1, i32 %$x2" ++
       
   154     i"br i1 %$x, label %$if_br, label %$else_br" ++
   178     i"br i1 %$x, label %$if_br, label %$else_br" ++
   155     l"\n$if_br" ++
   179     l"\n$if_br" ++
   156     compile_exp(a1) ++
   180     compile_exp(e1) ++
   157     l"\n$else_br" ++ 
   181     l"\n$else_br" ++ 
   158     compile_exp(a2)
   182     compile_exp(e2)
   159   }
   183   }
   160   case KCall(x1, args) => {
   184 }
   161     s"Call $x1 ($args)"
   185 
   162   }
   186 /*  case Write(a1) => {
   163 /*
       
   164   case Call(name, args) => {
       
   165     val is = "I" * args.length
       
   166     args.map(a => compile_exp(a, env)).mkString ++
       
   167     i"invokestatic XXX/XXX/$name($is)I"
       
   168   }
       
   169   case Sequence(a1, a2) => {
       
   170     compile_exp(a1, env) ++ i"pop" ++ compile_exp(a2, env)
       
   171   }
       
   172   case Write(a1) => {
       
   173     compile_exp(a1, env) ++
   187     compile_exp(a1, env) ++
   174     i"dup" ++
   188     i"dup" ++
   175     i"invokestatic XXX/XXX/write(I)V"
   189     i"invokestatic XXX/XXX/write(I)V"
   176   }
   190   }
   177   */
       
   178 }
       
   179 
       
   180 /*
       
   181 // compile boolean expressions
       
   182 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match {
       
   183   case Bop("==", a1, a2) => 
       
   184     compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"if_icmpne $jmp"
       
   185   case Bop("!=", a1, a2) => 
       
   186     compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"if_icmpeq $jmp"
       
   187   case Bop("<", a1, a2) => 
       
   188     compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"if_icmpge $jmp"
       
   189   case Bop("<=", a1, a2) => 
       
   190     compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"if_icmpgt $jmp"
       
   191 }
       
   192 */
   191 */
       
   192 
       
   193 
   193 
   194 
   194 // compile function for declarations and main
   195 // compile function for declarations and main
   195 def compile_decl(d: Decl) : String = d match {
   196 def compile_decl(d: Decl) : String = d match {
   196   case Def(name, args, body) => { 
   197   case Def(name, args, body) => { 
   197     println(s"DEF\n $name ($args) = \nBODY:")
   198     //println(s"DEF\n $name ($args) = \nBODY:")
   198     println(Denest(K(body)))
   199     //println(CPSi(body))
   199     println()
   200     //println()
   200     counter = -1
   201     //counter = -1
   201     m"define i32 @$name (${args.mkString("i32 %", ", i32 %", "")}) {" ++
   202     m"define i32 @$name (${args.mkString("i32 %", ", i32 %", "")}) {" ++
   202     compile_exp(Denest(K(body))) ++
   203     compile_exp(CPSi(body)) ++
   203     m"}\n"
   204     m"}\n"
   204   }
   205   }
   205   case Main(body) => {
   206   case Main(body) => {
   206     m"define i32 @main() {" ++
   207     m"define i32 @main() {" ++
   207     compile_exp(Denest(K(body))) ++
   208     compile_exp(CPSi(body)) ++
   208     i"ret i32 0" ++
       
   209     m"}\n"
   209     m"}\n"
   210   }
   210   }
   211 }
   211 }
   212 
   212 
   213 // main compiler functions
   213 // main compiler functions
   226   }
   226   }
   227 }
   227 }
   228 
   228 
   229 def compile(class_name: String) : String = {
   229 def compile(class_name: String) : String = {
   230   val ast = deserialise[List[Decl]](class_name ++ ".prs").getOrElse(Nil) 
   230   val ast = deserialise[List[Decl]](class_name ++ ".prs").getOrElse(Nil) 
   231   println(ast(0).toString ++ "\n")
   231   //println(ast(0).toString ++ "\n")
   232   val instructions = List(ast(0), ast(2)).map(compile_decl).mkString
   232   ast.map(compile_decl).mkString
   233   instructions
       
   234 }
   233 }
   235 
   234 
   236 /*
   235 /*
   237 def compile_to_file(class_name: String) = {
   236 def compile_to_file(class_name: String) = {
   238   val output = compile(class_name)
   237   val output = compile(class_name)