64 abstract class KExp |
64 abstract class KExp |
65 abstract class KVal |
65 abstract class KVal |
66 |
66 |
67 case class KVar(s: String) extends KVal |
67 case class KVar(s: String) extends KVal |
68 case class KNum(i: Int) extends KVal |
68 case class KNum(i: Int) extends KVal |
69 case class KAop(o: String, v1: KVal, v2: KVal) extends KVal |
69 case class Kop(o: String, v1: KVal, v2: KVal) extends KVal |
70 case class KBop(o: String, v1: KVal, v2: KVal) extends KVal |
|
71 case class KCall(o: String, vrs: List[KVal]) extends KVal |
70 case class KCall(o: String, vrs: List[KVal]) extends KVal |
72 case class KWrite(v: KVal) extends KVal |
71 case class KWrite(v: KVal) extends KVal |
73 |
72 |
74 case class KIf(x1: String, e1: KExp, e2: KExp) extends KExp { |
73 case class KIf(x1: String, e1: KExp, e2: KExp) extends KExp { |
75 override def toString = s"KIf $x1\nIF\n$e1\nELSE\n$e2" |
74 override def toString = s"KIf $x1\nIF\n$e1\nELSE\n$e2" |
86 case Var(s) => k(KVar(s)) |
85 case Var(s) => k(KVar(s)) |
87 case Num(i) => k(KNum(i)) |
86 case Num(i) => k(KNum(i)) |
88 case Aop(o, e1, e2) => { |
87 case Aop(o, e1, e2) => { |
89 val z = Fresh("tmp") |
88 val z = Fresh("tmp") |
90 CPS(e1)(y1 => |
89 CPS(e1)(y1 => |
91 CPS(e2)(y2 => KLet(z, KAop(o, y1, y2), k(KVar(z))))) |
90 CPS(e2)(y2 => KLet(z, Kop(o, y1, y2), k(KVar(z))))) |
92 } |
91 } |
93 case If(Bop(o, b1, b2), e1, e2) => { |
92 case If(Bop(o, b1, b2), e1, e2) => { |
94 val z = Fresh("tmp") |
93 val z = Fresh("tmp") |
95 CPS(b1)(y1 => |
94 CPS(b1)(y1 => |
96 CPS(b2)(y2 => |
95 CPS(b2)(y2 => |
97 KLet(z, KBop(o, y1, y2), KIf(z, CPS(e1)(k), CPS(e2)(k))))) |
96 KLet(z, Kop(o, y1, y2), KIf(z, CPS(e1)(k), CPS(e2)(k))))) |
98 } |
97 } |
99 case Call(name, args) => { |
98 case Call(name, args) => { |
100 def aux(args: List[Exp], vs: List[KVal]) : KExp = args match { |
99 def aux(args: List[Exp], vs: List[KVal]) : KExp = args match { |
101 case Nil => { |
100 case Nil => { |
102 val z = Fresh("tmp") |
101 val z = Fresh("tmp") |
104 } |
103 } |
105 case e::es => CPS(e)(y => aux(es, vs ::: List(y))) |
104 case e::es => CPS(e)(y => aux(es, vs ::: List(y))) |
106 } |
105 } |
107 aux(args, Nil) |
106 aux(args, Nil) |
108 } |
107 } |
109 case Sequence(e1, e2) => { |
108 case Sequence(e1, e2) => |
110 val z = Fresh("tmp") |
109 CPS(e1)(y1 => CPS(e2)(y2 => k(y2))) |
111 CPS(e1)(y1 => |
|
112 CPS(e2)(y2 => KLet("_", y1, KLet(z, y2, k(KVar(z)))))) |
|
113 } |
|
114 case Write(e) => { |
110 case Write(e) => { |
115 val z = Fresh("tmp") |
111 val z = Fresh("tmp") |
116 CPS(e)(y => KLet(z, KWrite(y), k(KVar(z)))) |
112 CPS(e)(y => KLet(z, KWrite(y), k(KVar(z)))) |
117 } |
113 } |
118 } |
114 } |
162 def i(args: Any*): String = " " ++ sc.s(args:_*) ++ "\n" |
158 def i(args: Any*): String = " " ++ sc.s(args:_*) ++ "\n" |
163 def l(args: Any*): String = sc.s(args:_*) ++ ":\n" |
159 def l(args: Any*): String = sc.s(args:_*) ++ ":\n" |
164 def m(args: Any*): String = sc.s(args:_*) ++ "\n" |
160 def m(args: Any*): String = sc.s(args:_*) ++ "\n" |
165 } |
161 } |
166 |
162 |
|
163 // mathematical and boolean operations |
167 def compile_op(op: String) = op match { |
164 def compile_op(op: String) = op match { |
168 case "+" => "add i32 " |
165 case "+" => "add i32 " |
169 case "*" => "mul i32 " |
166 case "*" => "mul i32 " |
170 case "-" => "sub i32 " |
167 case "-" => "sub i32 " |
|
168 case "/" => "sdiv i32 " |
|
169 case "%" => "srem i32 " |
171 case "==" => "icmp eq i32 " |
170 case "==" => "icmp eq i32 " |
|
171 case "<=" => "icmp sle i32 " // signed less or equal |
|
172 case "<" => "icmp slt i32 " // signed less than |
172 } |
173 } |
173 |
174 |
174 def compile_val(v: KVal) : String = v match { |
175 def compile_val(v: KVal) : String = v match { |
175 case KNum(i) => s"$i" |
176 case KNum(i) => s"$i" |
176 case KVar(s) => s"%$s" |
177 case KVar(s) => s"%$s" |
177 case KAop(op, x1, x2) => |
178 case Kop(op, x1, x2) => |
178 s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}" |
|
179 case KBop(op, x1, x2) => |
|
180 s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}" |
179 s"${compile_op(op)} ${compile_val(x1)}, ${compile_val(x2)}" |
181 case KCall(x1, args) => |
180 case KCall(x1, args) => |
182 s"call i32 @$x1 (${args.map(compile_val).mkString("i32 ", ", i32 ", "")})" |
181 s"call i32 @$x1 (${args.map(compile_val).mkString("i32 ", ", i32 ", "")})" |
183 case KWrite(x1) => |
182 case KWrite(x1) => |
184 s"call i32 @printInt (i32 ${compile_val(x1)})" |
183 s"call i32 @printInt (i32 ${compile_val(x1)})" |