progs/fun_llvm.scala
changeset 654 fb6192488b91
parent 653 9d7843934d30
child 655 3d04ee04966d
equal deleted inserted replaced
653:9d7843934d30 654:fb6192488b91
     1 // A Small Compiler for a Simple Functional Language
     1 // A Small LLVM Compiler for a Simple Functional Language
     2 // (includes an external lexer and parser)
     2 // (includes an external lexer and parser)
     3 //
     3 //
     4 // call with 
     4 // call with 
     5 //
     5 //
     6 //     scala fun.scala fact
     6 //     scala fun_llvm.scala fact
     7 //
     7 //
     8 //     scala fun.scala defs
     8 //     scala fun_llvm.scala defs
     9 //
     9 //
    10 // this will generate a .j file and run the jasmin
    10 // this will generate a .ll file
    11 // assembler (installed at jvm/jasmin-2.4/jasmin.jar)
       
    12 // it runs the resulting JVM file twice for timing 
       
    13 // purposes.
       
    14 
       
    15 
       
    16 
    11 
    17 
    12 
    18 object Compiler {
    13 object Compiler {
    19 
    14 
    20 import java.io._  
    15 import java.io._  
    50 def Fresh(x: String) = {
    45 def Fresh(x: String) = {
    51   counter += 1
    46   counter += 1
    52   x ++ "_" ++ counter.toString()
    47   x ++ "_" ++ counter.toString()
    53 }
    48 }
    54 
    49 
    55 
       
    56 
       
    57 // Abstract syntax trees for the Fun language
    50 // Abstract syntax trees for the Fun language
    58 abstract class KExp
    51 abstract class KExp
    59 abstract class KVal
    52 abstract class KVal
    60 
    53 
    61 case class KVar(s: String) extends KVal
    54 case class KVar(s: String) extends KVal
    70 case class KLet(x: String, e1: KVal, e2: KExp) extends KExp {
    63 case class KLet(x: String, e1: KVal, e2: KExp) extends KExp {
    71   override def toString = s"let $x = $e1 in \n$e2" 
    64   override def toString = s"let $x = $e1 in \n$e2" 
    72 }
    65 }
    73 case class KReturn(v: KVal) extends KExp
    66 case class KReturn(v: KVal) extends KExp
    74 
    67 
       
    68 
       
    69 // CPS translation from Exp's to KExp's using a
       
    70 // continuation k.
    75 def CPS(e: Exp)(k: KVal => KExp) : KExp = e match {
    71 def CPS(e: Exp)(k: KVal => KExp) : KExp = e match {
    76   case Var(s) => k(KVar(s)) 
    72   case Var(s) => k(KVar(s)) 
    77   case Num(i) => k(KNum(i))
    73   case Num(i) => k(KNum(i))
    78   case Aop(o, e1, e2) => {
    74   case Aop(o, e1, e2) => {
    79     val z = Fresh("tmp")
    75     val z = Fresh("tmp")
   102   }
    98   }
   103 }   
    99 }   
   104 
   100 
   105 def CPSi(e: Exp) = CPS(e)(KReturn)
   101 def CPSi(e: Exp) = CPS(e)(KReturn)
   106 
   102 
       
   103 // some testcases
   107 val e1 = Aop("*", Var("a"), Num(3))
   104 val e1 = Aop("*", Var("a"), Num(3))
   108 CPS(e1)(KReturn)
   105 CPSi(e1)
   109 
   106 
   110 val e2 = Aop("+", Aop("*", Var("a"), Num(3)), Num(4))
   107 val e2 = Aop("+", Aop("*", Var("a"), Num(3)), Num(4))
   111 CPS(e2)(KReturn)
   108 CPSi(e2)
   112 
   109 
   113 val e3 = Aop("+", Num(2), Aop("*", Var("a"), Num(3)))
   110 val e3 = Aop("+", Num(2), Aop("*", Var("a"), Num(3)))
   114 CPS(e3)(KReturn)
   111 CPSi(e3)
   115 
   112 
   116 val e4 = Aop("+", Aop("-", Num(1), Num(2)), Aop("*", Var("a"), Num(3)))
   113 val e4 = Aop("+", Aop("-", Num(1), Num(2)), Aop("*", Var("a"), Num(3)))
   117 CPS(e4)(KReturn)
   114 CPSi(e4)
   118 
   115 
   119 val e5 = If(Bop("==", Num(1), Num(1)), Num(3), Num(4))
   116 val e5 = If(Bop("==", Num(1), Num(1)), Num(3), Num(4))
   120 CPS(e5)(KReturn)
   117 CPSi(e5)
   121 
   118 
   122 val e6 = If(Bop("!=", Num(10), Num(10)), e5, Num(40))
   119 val e6 = If(Bop("!=", Num(10), Num(10)), e5, Num(40))
   123 CPS(e6)(KReturn)
   120 CPSi(e6)
   124 
   121 
   125 val e7 = Call("foo", List(Num(3)))
   122 val e7 = Call("foo", List(Num(3)))
   126 CPS(e7)(KReturn)
   123 CPSi(e7)
   127 
   124 
   128 val e8 = Call("foo", List(Num(3), Num(4), Aop("+", Num(5), Num(6))))
   125 val e8 = Call("foo", List(Num(3), Num(4), Aop("+", Num(5), Num(6))))
   129 CPS(e8)(KReturn)
   126 CPSi(e8)
   130 
   127 
   131 val e9 = Sequence(Aop("*", Var("a"), Num(3)), Aop("+", Var("b"), Num(6)))
   128 val e9 = Sequence(Aop("*", Var("a"), Num(3)), Aop("+", Var("b"), Num(6)))
   132 CPS(e9)(KReturn)
   129 CPSi(e9)
   133 
   130 
   134 val e = Aop("*", Aop("+", Num(1), Call("foo", List(Var("a"), Num(3)))), Num(4))
   131 val e = Aop("*", Aop("+", Num(1), Call("foo", List(Var("a"), Num(3)))), Num(4))
   135 CPS(e)(KReturn)
   132 CPSi(e)
   136 
   133 
   137 
   134 
   138 
   135 
   139 
   136 
   140 // convenient string interpolations 
   137 // convenient string interpolations 
   193 
   190 
   194 
   191 
   195 // compile function for declarations and main
   192 // compile function for declarations and main
   196 def compile_decl(d: Decl) : String = d match {
   193 def compile_decl(d: Decl) : String = d match {
   197   case Def(name, args, body) => { 
   194   case Def(name, args, body) => { 
   198     //println(s"DEF\n $name ($args) = \nBODY:")
       
   199     //println(CPSi(body))
       
   200     //println()
       
   201     //counter = -1
       
   202     m"define i32 @$name (${args.mkString("i32 %", ", i32 %", "")}) {" ++
   195     m"define i32 @$name (${args.mkString("i32 %", ", i32 %", "")}) {" ++
   203     compile_exp(CPSi(body)) ++
   196     compile_exp(CPSi(body)) ++
   204     m"}\n"
   197     m"}\n"
   205   }
   198   }
   206   case Main(body) => {
   199   case Main(body) => {
   226   }
   219   }
   227 }
   220 }
   228 
   221 
   229 def compile(class_name: String) : String = {
   222 def compile(class_name: String) : String = {
   230   val ast = deserialise[List[Decl]](class_name ++ ".prs").getOrElse(Nil) 
   223   val ast = deserialise[List[Decl]](class_name ++ ".prs").getOrElse(Nil) 
   231   //println(ast(0).toString ++ "\n")
       
   232   ast.map(compile_decl).mkString
   224   ast.map(compile_decl).mkString
   233 }
   225 }
   234 
   226 
   235 /*
   227 /*
   236 def compile_to_file(class_name: String) = {
   228 def compile_to_file(class_name: String) = {