solution/cw5/fun_llvm.sc
author Christian Urban <christian.urban@kcl.ac.uk>
Sun, 09 Oct 2022 13:39:34 +0100
changeset 882 5fcad75ade92
parent 868 8fb3b6d3be70
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     1
// A Small LLVM Compiler for a Simple Functional Language
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     2
// (includes an external lexer and parser)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     3
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     4
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     5
// call with                 -- prints out llvm code
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     6
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     7
//     amm fun_llvm.sc main fact.fun
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     8
//     amm fun_llvm.sc main defs.fun
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     9
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    10
// or                        -- writes llvm code to disk
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    11
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    12
//     amm fun_llvm.sc write fact.fun
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    13
//     amm fun_llvm.sc write defs.fun
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    14
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    15
//       this will generate an .ll file. 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    16
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    17
// or                       -- runs the generated llvm code via lli
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    18
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    19
//     amm fun_llvm.sc run fact.fun
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    20
//     amm fun_llvm.sc run defs.fun
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    21
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    22
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    23
// You can interpret an .ll file using lli, for example
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    24
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    25
//      lli fact.ll
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    26
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    27
// The optimiser can be invoked as
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    28
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    29
//      opt -O1 -S in_file.ll > out_file.ll
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    30
//      opt -O3 -S in_file.ll > out_file.ll
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    31
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    32
// The code produced for the various architectures can be obtain with
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    33
//   
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    34
//   llc -march=x86 -filetype=asm in_file.ll -o -
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    35
//   llc -march=arm -filetype=asm in_file.ll -o -  
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    36
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    37
// Producing an executable can be achieved by
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    38
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    39
//    llc -filetype=obj in_file.ll
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    40
//    gcc in_file.o -o a.out
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    41
//    ./a.out
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    42
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    43
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    44
import $file.fun_tokens, fun_tokens._
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    45
import $file.fun_parser, fun_parser._ 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    46
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    47
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    48
// for generating new labels
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    49
var counter = -1
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    50
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    51
def Fresh(x: String) = {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    52
  counter += 1
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    53
  x ++ "_" ++ counter.toString()
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    54
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    55
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    56
// Internal CPS language for FUN
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    57
abstract class KExp
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    58
abstract class KVal
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    59
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    60
type Ty = String
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    61
type TyEnv = Map[String, Ty]
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    62
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    63
case class KVar(s: String, ty: Ty = "UNDEF") extends KVal
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    64
case class KLoad(v: KVal) extends KVal
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    65
case class KNum(i: Int) extends KVal
868
8fb3b6d3be70 updated to Doubles trhoughout
Christian Urban <christian.urban@kcl.ac.uk>
parents: 867
diff changeset
    66
case class KFNum(i: Double) extends KVal
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    67
case class KChr(c: Int) extends KVal
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    68
case class Kop(o: String, v1: KVal, v2: KVal, ty: Ty = "UNDEF") extends KVal
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    69
case class KCall(o: String, vrs: List[KVal], ty: Ty = "UNDEF") extends KVal
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    70
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    71
case class KIf(x1: String, e1: KExp, e2: KExp) extends KExp {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    72
  override def toString = s"KIf $x1\nIF\n$e1\nELSE\n$e2"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    73
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    74
case class KLet(x: String, e1: KVal, e2: KExp) extends KExp {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    75
  override def toString = s"let $x = $e1 in \n$e2" 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    76
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    77
case class KReturn(v: KVal) extends KExp
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    78
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    79
// typing K values
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    80
def typ_val(v: KVal, ts: TyEnv) : (KVal, Ty) = v match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    81
  case KVar(s, _) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    82
    val ty = ts.getOrElse(s, "TUNDEF")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    83
    (KVar(s, ty), ty)  
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    84
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    85
  case Kop(op, v1, v2, _) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    86
    val (tv1, ty1) = typ_val(v1, ts)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    87
    val (tv2, ty2) = typ_val(v2, ts)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    88
    if (ty1 == ty2) (Kop(op, tv1, tv2, ty1), ty1) else (Kop(op, tv1, tv2, "TMISMATCH"), "TMISMATCH") 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    89
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    90
  case KCall(fname, args, _) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    91
    val ty = ts.getOrElse(fname, "TCALLUNDEF" ++ fname)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    92
    (KCall(fname, args.map(typ_val(_, ts)._1), ty), ty)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    93
  }  
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    94
  case KLoad(v) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    95
    val (tv, ty) = typ_val(v, ts)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    96
    (KLoad(tv), ty)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    97
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    98
  case KNum(i) => (KNum(i), "Int")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    99
  case KFNum(i) => (KFNum(i), "Double")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   100
  case KChr(c) => (KChr(c), "Int")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   101
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   102
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   103
def typ_exp(a: KExp, ts: TyEnv) : KExp = a match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   104
  case KReturn(v) => KReturn(typ_val(v, ts)._1)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   105
  case KLet(x: String, v: KVal, e: KExp) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   106
    val (tv, ty) = typ_val(v, ts)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   107
    KLet(x, tv, typ_exp(e, ts + (x -> ty)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   108
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   109
  case KIf(b, e1, e2) => KIf(b, typ_exp(e1, ts), typ_exp(e2, ts))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   110
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   111
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   112
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   113
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   114
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   115
// CPS translation from Exps to KExps using a
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   116
// continuation k.
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   117
def CPS(e: Exp)(k: KVal => KExp) : KExp = e match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   118
  case Var(s) if (s.head.isUpper) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   119
      val z = Fresh("tmp")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   120
      KLet(z, KLoad(KVar(s)), k(KVar(z)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   121
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   122
  case Var(s) => k(KVar(s))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   123
  case Num(i) => k(KNum(i))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   124
  case ChConst(c) => k(KChr(c))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   125
  case FNum(i) => k(KFNum(i))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   126
  case Aop(o, e1, e2) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   127
    val z = Fresh("tmp")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   128
    CPS(e1)(y1 => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   129
      CPS(e2)(y2 => KLet(z, Kop(o, y1, y2), k(KVar(z)))))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   130
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   131
  case If(Bop(o, b1, b2), e1, e2) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   132
    val z = Fresh("tmp")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   133
    CPS(b1)(y1 => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   134
      CPS(b2)(y2 => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   135
        KLet(z, Kop(o, y1, y2), KIf(z, CPS(e1)(k), CPS(e2)(k)))))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   136
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   137
  case Call(name, args) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   138
    def aux(args: List[Exp], vs: List[KVal]) : KExp = args match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   139
      case Nil => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   140
          val z = Fresh("tmp")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   141
          KLet(z, KCall(name, vs), k(KVar(z)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   142
      }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   143
      case e::es => CPS(e)(y => aux(es, vs ::: List(y)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   144
    }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   145
    aux(args, Nil)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   146
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   147
  case Sequence(e1, e2) => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   148
    CPS(e1)(_ => CPS(e2)(y2 => k(y2)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   149
}   
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   150
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   151
//initial continuation
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   152
def CPSi(e: Exp) = CPS(e)(KReturn)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   153
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   154
// some testcases
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   155
val e1 = Aop("*", Var("a"), Num(3))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   156
CPSi(e1)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   157
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   158
val e2 = Aop("+", Aop("*", Var("a"), Num(3)), Num(4))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   159
CPSi(e2)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   160
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   161
val e3 = Aop("+", Num(2), Aop("*", Var("a"), Num(3)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   162
CPSi(e3)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   163
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   164
val e4 = Aop("+", Aop("-", Num(1), Num(2)), Aop("*", Var("a"), Num(3)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   165
CPSi(e4)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   166
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   167
val e5 = If(Bop("==", Num(1), Num(1)), Num(3), Num(4))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   168
CPSi(e5)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   169
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   170
val e6 = If(Bop("!=", Num(10), Num(10)), e5, Num(40))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   171
CPSi(e6)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   172
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   173
val e7 = Call("foo", List(Num(3)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   174
CPSi(e7)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   175
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   176
val e8 = Call("foo", List(Aop("*", Num(3), Num(1)), Num(4), Aop("+", Num(5), Num(6))))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   177
CPSi(e8)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   178
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   179
val e9 = Sequence(Aop("*", Var("a"), Num(3)), Aop("+", Var("b"), Num(6)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   180
CPSi(e9)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   181
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   182
val e = Aop("*", Aop("+", Num(1), Call("foo", List(Var("a"), Num(3)))), Num(4))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   183
CPSi(e)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   184
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   185
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   186
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   187
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   188
// convenient string interpolations 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   189
// for instructions, labels and methods
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   190
import scala.language.implicitConversions
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   191
import scala.language.reflectiveCalls
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   192
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   193
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   194
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   195
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   196
implicit def sring_inters(sc: StringContext) = new {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   197
    def i(args: Any*): String = "   " ++ sc.s(args:_*) ++ "\n"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   198
    def l(args: Any*): String = sc.s(args:_*) ++ ":\n"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   199
    def m(args: Any*): String = sc.s(args:_*) ++ "\n"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   200
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   201
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   202
def get_ty(s: String) = s match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   203
  case "Double" => "double"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   204
  case "Void" => "void"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   205
  case "Int" => "i32"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   206
  case "Bool" => "i2"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   207
  case _ => s
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   208
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   209
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   210
def compile_call_arg(a: KVal) = a match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   211
  case KNum(i) => s"i32 $i"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   212
  case KFNum(i) => s"double $i"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   213
  case KChr(c) => s"i32 $c"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   214
  case KVar(s, ty) => s"${get_ty(ty)} %$s" 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   215
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   216
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   217
def compile_arg(s: (String, String)) = s"${get_ty(s._2)} %${s._1}" 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   218
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   219
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   220
// mathematical and boolean operations
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   221
def compile_op(op: String) = op match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   222
  case "+" => "add i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   223
  case "*" => "mul i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   224
  case "-" => "sub i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   225
  case "/" => "sdiv i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   226
  case "%" => "srem i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   227
  case "==" => "icmp eq i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   228
  case "!=" => "icmp ne i32 "      // not equal 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   229
  case "<=" => "icmp sle i32 "     // signed less or equal
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   230
  case "<"  => "icmp slt i32 "     // signed less than
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   231
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   232
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   233
def compile_dop(op: String) = op match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   234
  case "+" => "fadd double "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   235
  case "*" => "fmul double "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   236
  case "-" => "fsub double "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   237
  case "==" => "fcmp oeq double "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   238
  case "<=" => "fcmp ole double "   
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   239
  case "<"  => "fcmp olt double "   
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   240
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   241
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   242
// compile K values
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   243
def compile_val(v: KVal) : String = v match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   244
  case KNum(i) => s"$i"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   245
  case KFNum(i) => s"$i"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   246
  case KChr(c) => s"$c"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   247
  case KVar(s, ty) => s"%$s" 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   248
  case KLoad(KVar(s, ty)) => s"load ${get_ty(ty)}, ${get_ty(ty)}* @$s"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   249
  case Kop(op, x1, x2, ty) => ty match { 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   250
    case "Int" => s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   251
    case "Double" => s"${compile_dop(op)} ${compile_val(x1)}, ${compile_val(x2)}"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   252
    case _ => Kop(op, x1, x2, ty).toString
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   253
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   254
  case KCall(fname, args, ty) => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   255
    s"call ${get_ty(ty)} @$fname (${args.map(compile_call_arg).mkString(", ")})"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   256
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   257
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   258
// compile K expressions
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   259
def compile_exp(a: KExp) : String = a match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   260
  case KReturn(KVar("void", _)) =>
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   261
    i"ret void"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   262
  case KReturn(KVar(x, ty)) =>
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   263
    i"ret ${get_ty(ty)} %$x"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   264
  case KReturn(KNum(i)) =>
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   265
    i"ret i32 $i"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   266
  case KLet(x: String, KCall(o: String, vrs: List[KVal], "Void"), e: KExp) => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   267
    i"${compile_val(KCall(o: String, vrs: List[KVal], "Void"))}" ++ compile_exp(e)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   268
  case KLet(x: String, v: KVal, e: KExp) => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   269
    i"%$x = ${compile_val(v)}" ++ compile_exp(e)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   270
  case KIf(x, e1, e2) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   271
    val if_br = Fresh("if_branch")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   272
    val else_br = Fresh("else_branch")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   273
    i"br i1 %$x, label %$if_br, label %$else_br" ++
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   274
    l"\n$if_br" ++
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   275
    compile_exp(e1) ++
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   276
    l"\n$else_br" ++ 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   277
    compile_exp(e2)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   278
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   279
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   280
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   281
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   282
val prelude = """
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   283
declare i32 @printf(i8*, ...)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   284
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   285
@.str_nl = private constant [2 x i8] c"\0A\00"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   286
@.str_star = private constant [2 x i8] c"*\00"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   287
@.str_space = private constant [2 x i8] c" \00"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   288
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   289
define void @new_line() #0 {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   290
  %t0 = getelementptr [2 x i8], [2 x i8]* @.str_nl, i32 0, i32 0
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   291
  %1 = call i32 (i8*, ...) @printf(i8* %t0)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   292
  ret void
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   293
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   294
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   295
define void @print_star() #0 {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   296
  %t0 = getelementptr [2 x i8], [2 x i8]* @.str_star, i32 0, i32 0
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   297
  %1 = call i32 (i8*, ...) @printf(i8* %t0)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   298
  ret void
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   299
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   300
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   301
define void @print_space() #0 {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   302
  %t0 = getelementptr [2 x i8], [2 x i8]* @.str_space, i32 0, i32 0
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   303
  %1 = call i32 (i8*, ...) @printf(i8* %t0)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   304
  ret void
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   305
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   306
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   307
define void @skip() #0 {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   308
  ret void
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   309
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   310
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   311
@.str_int = private constant [3 x i8] c"%d\00"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   312
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   313
define void @print_int(i32 %x) {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   314
   %t0 = getelementptr [3 x i8], [3 x i8]* @.str_int, i32 0, i32 0
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   315
   call i32 (i8*, ...) @printf(i8* %t0, i32 %x) 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   316
   ret void
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   317
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   318
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   319
@.str_char = private constant [3 x i8] c"%c\00"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   320
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   321
define void @print_char(i32 %x) {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   322
   %t0 = getelementptr [3 x i8], [3 x i8]* @.str_char, i32 0, i32 0
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   323
   call i32 (i8*, ...) @printf(i8* %t0, i32 %x) 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   324
   ret void
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   325
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   326
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   327
; END OF BUILD-IN FUNCTIONS (prelude)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   328
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   329
"""
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   330
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   331
def get_cont(ty: Ty) = ty match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   332
  case "Int" =>    KReturn
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   333
  case "Double" => KReturn
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   334
  case "Void" =>   { (_: KVal) => KReturn(KVar("void", "Void")) }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   335
} 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   336
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   337
// compile function for declarations and main
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   338
def compile_decl(d: Decl, ts: TyEnv) : (String, TyEnv) = d match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   339
  case Def(name, args, ty, body) => { 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   340
    val ts2 = ts + (name -> ty)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   341
    val tkbody = typ_exp(CPS(body)(get_cont(ty)), ts2 ++ args.toMap)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   342
    (m"define ${get_ty(ty)} @$name (${args.map(compile_arg).mkString(",")}) {" ++
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   343
     compile_exp(tkbody) ++
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   344
     m"}\n", ts2)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   345
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   346
  case Main(body) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   347
    val tbody = typ_exp(CPS(body)(_ => KReturn(KNum(0))), ts)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   348
    (m"define i32 @main() {" ++
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   349
     compile_exp(tbody) ++
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   350
     m"}\n", ts)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   351
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   352
  case Const(name, n) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   353
    (m"@$name = global i32 $n\n", ts + (name -> "Int"))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   354
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   355
  case FConst(name, x) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   356
    (m"@$name = global double $x\n", ts + (name -> "Double"))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   357
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   358
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   359
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   360
def compile_prog(prog: List[Decl], ty: TyEnv) : String = prog match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   361
  case Nil => ""
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   362
  case d::ds => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   363
    val (s2, ty2) = compile_decl(d, ty)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   364
    s2 ++ compile_prog(ds, ty2)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   365
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   366
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   367
// main compiler functions
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   368
def compile(prog: List[Decl]) : String = 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   369
  prelude ++ compile_prog(prog, Map("new_line" -> "Void", "skip" -> "Void", 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   370
				    "print_star" -> "Void", "print_space" -> "Void",
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   371
                                    "print_int" -> "Void", "print_char" -> "Void"))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   372
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   373
867
54bcd848d716 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 864
diff changeset
   374
//import ammonite.ops._
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   375
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   376
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   377
@main
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   378
def main(fname: String) = {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   379
    val path = os.pwd / fname
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   380
    val file = fname.stripSuffix("." ++ path.ext)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   381
    val tks = tokenise(os.read(path))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   382
    val ast = parse_tks(tks)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   383
    val code = compile(ast)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   384
    println(code)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   385
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   386
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   387
@main
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   388
def write(fname: String) = {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   389
    val path = os.pwd / fname
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   390
    val file = fname.stripSuffix("." ++ path.ext)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   391
    val tks = tokenise(os.read(path))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   392
    val ast = parse_tks(tks)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   393
    val code = compile(ast)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   394
    //println(code)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   395
    os.write.over(os.pwd / (file ++ ".ll"), code)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   396
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   397
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   398
@main
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   399
def run(fname: String) = {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   400
    val path = os.pwd / fname
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   401
    val file = fname.stripSuffix("." ++ path.ext)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   402
    write(fname)  
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   403
    os.proc("llc", "-filetype=obj", file ++ ".ll").call()
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   404
    os.proc("gcc", file ++ ".o", "-o", file ++ ".bin").call()
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   405
    os.proc(os.pwd / (file ++ ".bin")).call(stdout = os.Inherit)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   406
    println(s"done.")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   407
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   408
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   409
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   410
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   411
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   412