solutions/cw5/fun_llvm.sc
author Christian Urban <christian.urban@kcl.ac.uk>
Fri, 25 Oct 2024 18:54:08 +0100
changeset 971 51e00f223792
parent 921 bb54e7aa1a3f
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
     1
// Author: Zhuo Ying Jiang Li
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
     2
// Starting code by Dr Christian Urban
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
     3
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
     4
// 
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
     5
// Use amm compiler.sc XXX.fun
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
     6
// ./XXX
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
     7
// This will generate XXX.ll, XXX.o as well as the binary program.
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     8
//
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
     9
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    10
// lexer + parser
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    11
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    12
import $file.fun_tokens, fun_tokens._
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    13
import $file.fun_parser, fun_parser._ 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    14
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    15
// for generating new labels
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    16
var counter = -1
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    17
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    18
def Fresh(x: String) = {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    19
  counter += 1
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    20
  x ++ "_" ++ counter.toString()
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    21
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    22
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    23
// typing
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    24
type Ty = String
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    25
type TyEnv = Map[String, Ty]
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    26
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    27
// initial typing environment
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    28
val initialEnv = Map[String, Ty]("skip" -> "Void", "print_int" -> "Void", "print_char" -> "Void",
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    29
                                "print_space" -> "Void", "print_star" -> "Void", "new_line" -> "Void")
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    30
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    31
val typeConversion = Map("Int" -> "i32", "Double" -> "double", "Void" -> "void")
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    32
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    33
// Internal CPS language for FUN
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    34
abstract class KExp
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    35
abstract class KVal
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    36
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    37
case class KVar(s: String, ty: Ty = "UNDEF") extends KVal
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    38
case class KConst(s: String, ty: Ty = "UNDEF") extends KVal
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    39
case class KNum(i: Int) extends KVal  // known type
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    40
case class KFNum(d: Float) extends KVal  // known type
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    41
case class KChConst(c: Int) extends KVal  // known type
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    42
case class Kop(o: String, v1: KVal, v2: KVal, ty: Ty = "UNDEF") extends KVal
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    43
case class KCall(o: String, vrs: List[KVal], ty: Ty = "UNDEF") extends KVal
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    44
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    45
case class KLet(x: String, e1: KVal, e2: KExp) extends KExp {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    46
  override def toString = s"LET $x = $e1 in \n$e2" 
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    47
}
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    48
case class KIf(x1: String, e1: KExp, e2: KExp) extends KExp {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    49
  def pad(e: KExp) = e.toString.replaceAll("(?m)^", "  ")
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    50
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    51
  override def toString = 
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    52
     s"IF $x1\nTHEN\n${pad(e1)}\nELSE\n${pad(e2)}"
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    53
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    54
case class KReturn(v: KVal) extends KExp
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    55
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    56
// CPS translation from Exps to KExps using a
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    57
// continuation k.
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    58
def CPS(e: Exp)(k: KVal => KExp) : KExp = e match {
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    59
  case Var(s) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    60
    if (s.head.isUpper) {  // if this variable is a global
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    61
      val z = Fresh("tmp")
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    62
      KLet(z, KConst(s), k(KVar(z)))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    63
    } else k(KVar(s))
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    64
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    65
  case Num(i) => k(KNum(i))
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    66
  case FNum(d) => k(KFNum(d))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    67
  case ChConst(c) => k(KChConst(c))
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    68
  case Aop(o, e1, e2) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    69
    val z = Fresh("tmp")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    70
    CPS(e1)(y1 => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    71
      CPS(e2)(y2 => KLet(z, Kop(o, y1, y2), k(KVar(z)))))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    72
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    73
  case If(Bop(o, b1, b2), e1, e2) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    74
    val z = Fresh("tmp")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    75
    CPS(b1)(y1 => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    76
      CPS(b2)(y2 => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    77
        KLet(z, Kop(o, y1, y2), KIf(z, CPS(e1)(k), CPS(e2)(k)))))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    78
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    79
  case Call(name, args) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    80
    def aux(args: List[Exp], vs: List[KVal]) : KExp = args match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    81
      case Nil => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    82
          val z = Fresh("tmp")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    83
          KLet(z, KCall(name, vs), k(KVar(z)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    84
      }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    85
      case e::es => CPS(e)(y => aux(es, vs ::: List(y)))
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    86
    }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    87
    aux(args, Nil)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    88
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    89
  case Sequence(e1, e2) => 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    90
    CPS(e1)(_ => CPS(e2)(y2 => k(y2)))
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    91
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    92
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    93
// initial continuation
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    94
def CPSi(e: Exp) = CPS(e)(KReturn)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    95
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
    96
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    97
// get type of KVal
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    98
def get_typ_val(v: KVal) : Ty = v match {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
    99
  case KNum(i) => "Int"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   100
  case KFNum(d) => "Double"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   101
  case KChConst(i) => "Int"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   102
  case KVar(name, ty) => ty
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   103
  case KConst(name, ty) => ty
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   104
  case Kop(o, v1, v2, ty) => ty
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   105
  case KCall(o, vrs, ty) => ty
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   106
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   107
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   108
// update type information for KValues
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   109
def typ_val(v: KVal, ts: TyEnv) : KVal = v match {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   110
  case KVar(name, ty) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   111
    if (ts.contains(name)) {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   112
      KVar(name, ts(name))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   113
    } else throw new Exception(s"Compile error: unknown type for $name")
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   114
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   115
  case KConst(name, ty) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   116
    if (ts.contains(name)) {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   117
      KConst(name, ts(name))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   118
    } else throw new Exception(s"Compile error: unknown type for $name")
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   119
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   120
  case Kop(o, v1, v2, ty) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   121
    val tv1 = typ_val(v1, ts)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   122
    val tv2 = typ_val(v2, ts)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   123
    val t1 = get_typ_val(tv1)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   124
    val t2 = get_typ_val(tv2)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   125
    if (t1 != t2) throw new Exception(s"Compile error: cannot compare $t1 with $t2")
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   126
    Kop(o, tv1, tv2, t1)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   127
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   128
  case KCall(o, vrs, ty) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   129
    val new_vrs = vrs.map(vr => typ_val(vr, ts))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   130
    if (ts.contains(o)) {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   131
      KCall(o, new_vrs, ts(o))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   132
    } else throw new Exception(s"Compile error: unknown type for $o")
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   133
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   134
  case x => x  // no changes: KNum, KFNum, KChConst
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   135
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   136
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   137
// update type information for KExpressions
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   138
def typ_exp(a: KExp, ts: TyEnv) : KExp = a match {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   139
  case KLet(x, e1, e2) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   140
    val te1 = typ_val(e1, ts)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   141
    val env1 = ts + (x -> get_typ_val(te1))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   142
    val te2 = typ_exp(e2, env1)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   143
    KLet(x, te1, te2)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   144
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   145
  case KIf(x1, e1, e2) => KIf(x1, typ_exp(e1, ts), typ_exp(e2, ts))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   146
  case KReturn(v) => KReturn(typ_val(v, ts))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   147
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   148
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   149
// prelude
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   150
val prelude = """
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   151
declare i32 @printf(i8*, ...)
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   152
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   153
@.str_nl = private constant [2 x i8] c"\0A\00"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   154
@.str_star = private constant [2 x i8] c"*\00"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   155
@.str_space = private constant [2 x i8] c" \00"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   156
@.str_int = private constant [3 x i8] c"%d\00"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   157
@.str_c = private constant [3 x i8] c"%c\00"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   158
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   159
define void @new_line() #0 {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   160
  %t0 = getelementptr [2 x i8], [2 x i8]* @.str_nl, i32 0, i32 0
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   161
  call i32 (i8*, ...) @printf(i8* %t0)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   162
  ret void
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   163
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   164
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   165
define void @print_star() #0 {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   166
  %t0 = getelementptr [2 x i8], [2 x i8]* @.str_star, i32 0, i32 0
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   167
  call i32 (i8*, ...) @printf(i8* %t0)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   168
  ret void
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   169
}
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   170
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   171
define void @print_space() #0 {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   172
  %t0 = getelementptr [2 x i8], [2 x i8]* @.str_space, i32 0, i32 0
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   173
  call i32 (i8*, ...) @printf(i8* %t0)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   174
  ret void
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   175
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   176
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   177
define void @print_int(i32 %x) {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   178
  %t0 = getelementptr [3 x i8], [3 x i8]* @.str_int, i32 0, i32 0
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   179
  call i32 (i8*, ...) @printf(i8* %t0, i32 %x) 
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   180
  ret void
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   181
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   182
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   183
define void @print_char(i32 %x) {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   184
  %t0 = getelementptr [3 x i8], [3 x i8]* @.str_c, i32 0, i32 0
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   185
  call i32 (i8*, ...) @printf(i8* %t0, i32 %x)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   186
  ret void
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   187
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   188
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   189
define void @skip() #0 {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   190
  ret void
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   191
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   192
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   193
; END OF BUILT-IN FUNCTIONS (prelude)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   194
"""
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   195
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   196
// convenient string interpolations 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   197
// for instructions, labels and methods
920
7af2eea19646 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 903
diff changeset
   198
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   199
920
7af2eea19646 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 903
diff changeset
   200
extension (sc: StringContext) {
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   201
    def i(args: Any*): String = "   " ++ sc.s(args:_*) ++ "\n"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   202
    def l(args: Any*): String = sc.s(args:_*) ++ ":\n"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   203
    def m(args: Any*): String = sc.s(args:_*) ++ "\n"
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   204
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   205
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   206
// mathematical and boolean operations
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   207
def compile_op(op: String) = op match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   208
  case "+" => "add i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   209
  case "*" => "mul i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   210
  case "-" => "sub i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   211
  case "/" => "sdiv i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   212
  case "%" => "srem i32 "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   213
  case "==" => "icmp eq i32 "
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   214
  case "!=" => "icmp ne i32 "
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   215
  case "<=" => "icmp sle i32 "
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   216
  case "<"  => "icmp slt i32 "
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   217
  case ">=" => "icmp sge i32 "
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   218
  case ">" => "icmp sgt i32 "
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   219
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   220
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   221
def compile_dop(op: String) = op match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   222
  case "+" => "fadd double "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   223
  case "*" => "fmul double "
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   224
  case "-" => "fsub double "
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   225
  case "/" => "fdiv double "
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   226
  case "%" => "frem double "
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   227
  case "==" => "fcmp oeq double "
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   228
  case "!=" => "fcmp one double "
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   229
  case "<=" => "fcmp ole double "
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   230
  case "<" => "fcmp olt double "
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   231
  case ">=" => "icmp sge double "
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   232
  case ">" => "icmp sgt double "
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   233
}
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   234
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   235
def compile_args(vrs: List[KVal]) : List[String] = vrs match {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   236
  case Nil => Nil
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   237
  case x::xs => s"${typeConversion(get_typ_val(x))} ${compile_val(x)}" :: compile_args(xs)
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   238
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   239
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   240
// compile K values
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   241
def compile_val(v: KVal) : String = v match {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   242
  case KNum(i) => s"$i"
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   243
  case KFNum(d) => s"$d"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   244
  case KChConst(i) => s"$i"  // as integer
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   245
  case KVar(s, ty) => s"%$s"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   246
  case KConst(s, ty) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   247
    val t = typeConversion(ty)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   248
    s"load $t, $t* @$s"
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   249
  }
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   250
  case Kop(op, x1, x2, ty) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   251
    if (ty == "Double") {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   252
      s"${compile_dop(op)} ${compile_val(x1)}, ${compile_val(x2)}"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   253
    } else if (ty == "Int") {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   254
      s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   255
    } else throw new Exception("Compile error: unknown type for comparison")
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   256
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   257
  case KCall(x1, args, ty) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   258
    s"call ${typeConversion(ty)} @$x1 (${compile_args(args).mkString(", ")})"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   259
  }
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   260
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   261
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   262
// compile K expressions
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   263
def compile_exp(a: KExp) : String = a match {
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   264
  case KReturn(v) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   265
    val ty = get_typ_val(v)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   266
    if (ty == "Void") {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   267
      i"ret void"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   268
    } else {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   269
      i"ret ${typeConversion(ty)} ${compile_val(v)}"
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   270
    }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   271
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   272
  case KLet(x: String, v: KVal, e: KExp) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   273
    val tv = get_typ_val(v)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   274
    if (tv == "Void") {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   275
      i"${compile_val(v)}" ++ compile_exp(e)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   276
    } else i"%$x = ${compile_val(v)}" ++ compile_exp(e)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   277
  }
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   278
  case KIf(x, e1, e2) => {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   279
    val if_br = Fresh("if_branch")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   280
    val else_br = Fresh("else_branch")
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   281
    i"br i1 %$x, label %$if_br, label %$else_br" ++
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   282
    l"\n$if_br" ++
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   283
    compile_exp(e1) ++
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   284
    l"\n$else_br" ++ 
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   285
    compile_exp(e2)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   286
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   287
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   288
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   289
def compile_def_args(args: List[(String, String)], ts: TyEnv) : (List[String], TyEnv) = args match {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   290
  case Nil => (Nil, ts)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   291
  case (n, t)::xs => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   292
    if (t == "Void") throw new Exception("Compile error: argument of type void is invalid")
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   293
    val (rest, env) = compile_def_args(xs, ts + (n -> t))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   294
    (s"${typeConversion(t)} %$n" :: rest, env)
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   295
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   296
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   297
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   298
def compile_decl(d: Decl, ts: TyEnv) : (String, TyEnv) = d match {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   299
  case Const(name, value) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   300
    (m"@$name = global i32 $value\n", ts + (name -> "Int"))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   301
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   302
  case FConst(name, value) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   303
    (m"@$name = global double $value\n", ts + (name -> "Double"))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   304
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   305
  case Def(name, args, ty, body) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   306
    val (argList, env1) = compile_def_args(args, ts + (name -> ty))
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   307
    (m"define ${typeConversion(ty)} @$name (${argList.mkString(", ")}) {" ++
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   308
    compile_exp(typ_exp(CPSi(body), env1)) ++
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   309
    m"}\n", ts + (name -> ty))  // don't preserve local variables in environment
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   310
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   311
  case Main(body) => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   312
    (m"define i32 @main() {" ++
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   313
    compile_exp(typ_exp(CPS(body)(_ => KReturn(KNum(0))), ts + ("main" -> "Int"))) ++
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   314
    m"}\n", ts + ("main" -> "Int"))
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   315
  }
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   316
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   317
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   318
// recursively update the typing environment while compiling
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   319
def compile_block(prog: List[Decl], ts: TyEnv) : (String, TyEnv) = prog match {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   320
  case Nil => ("", ts)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   321
  case x::xs => {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   322
    val (compiled, env) = compile_decl(x, ts)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   323
    val (compiled_block, env1) = compile_block(xs, env)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   324
    (compiled ++ compiled_block, env1)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   325
  }
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   326
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   327
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   328
def fun_compile(prog: List[Decl]) : String = {
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   329
  val tyenv = initialEnv
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   330
  val (compiled, _) = compile_block(prog, tyenv)
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   331
  prelude ++ compiled
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   332
}
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   333
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   334
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   335
@main
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   336
def main(fname: String) = {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   337
    val path = os.pwd / fname
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   338
    val file = fname.stripSuffix("." ++ path.ext)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   339
    val tks = tokenise(os.read(path))
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   340
    val ast = parse_tks(tks).head
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   341
    val code = fun_compile(ast)
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   342
    println(code)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   343
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   344
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   345
@main
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   346
def write(fname: String) = {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   347
    val path = os.pwd / fname
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   348
    val file = fname.stripSuffix("." ++ path.ext)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   349
    val tks = tokenise(os.read(path))
903
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   350
    val ast = parse_tks(tks).head
2f86ebda3629 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 894
diff changeset
   351
    val code = fun_compile(ast)
864
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   352
    //println(code)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   353
    os.write.over(os.pwd / (file ++ ".ll"), code)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   354
}
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   355
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   356
@main
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   357
def run(fname: String) = {
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   358
    val path = os.pwd / fname
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   359
    val file = fname.stripSuffix("." ++ path.ext)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   360
    write(fname)  
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   361
    os.proc("llc", "-filetype=obj", file ++ ".ll").call()
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   362
    os.proc("gcc", file ++ ".o", "-o", file ++ ".bin").call()
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   363
    os.proc(os.pwd / (file ++ ".bin")).call(stdout = os.Inherit)
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff changeset
   364
    println(s"done.")
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
921
bb54e7aa1a3f updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 920
diff changeset
   368
// for automated testing 
bb54e7aa1a3f updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 920
diff changeset
   369
bb54e7aa1a3f updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 920
diff changeset
   370
@main
bb54e7aa1a3f updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 920
diff changeset
   371
def test(fname: String) = write(fname)