116 implicit def sring_inters(sc: StringContext) = new { |
116 implicit def sring_inters(sc: StringContext) = new { |
117 def i(args: Any*): String = " " ++ sc.s(args:_*) ++ "\n" |
117 def i(args: Any*): String = " " ++ sc.s(args:_*) ++ "\n" |
118 def l(args: Any*): String = sc.s(args:_*) ++ ":\n" |
118 def l(args: Any*): String = sc.s(args:_*) ++ ":\n" |
119 } |
119 } |
120 |
120 |
|
121 // this allows you to write things like |
|
122 // i"add" and l"Lable" |
|
123 |
121 |
124 |
122 // environments |
125 // environments |
123 type Env = Map[String, Int] |
126 type Env = Map[String, Int] |
124 |
127 |
125 |
128 |
130 } |
133 } |
131 |
134 |
132 // arithmetic expression compilation |
135 // arithmetic expression compilation |
133 def compile_aexp(a: AExp, env : Env) : String = a match { |
136 def compile_aexp(a: AExp, env : Env) : String = a match { |
134 case Num(i) => i"ldc $i" |
137 case Num(i) => i"ldc $i" |
135 case Var(s) => i"iload ${env(s)}" |
138 case Var(s) => i"iload ${env(s)} \t\t; $s" |
136 case Aop(op, a1, a2) => |
139 case Aop(op, a1, a2) => |
137 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op) |
140 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op) |
138 } |
141 } |
139 |
142 |
140 // boolean expression compilation |
143 // boolean expression compilation |
|
144 // - the jump-label is for where to jump if the condition is not true |
141 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match { |
145 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match { |
142 case True => "" |
146 case True => "" |
143 case False => i"goto $jmp" |
147 case False => i"goto $jmp" |
144 case Bop("=", a1, a2) => |
148 case Bop("==", a1, a2) => |
145 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpne $jmp" |
149 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpne $jmp" |
146 case Bop("!=", a1, a2) => |
150 case Bop("!=", a1, a2) => |
147 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpeq $jmp" |
151 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpeq $jmp" |
148 case Bop("<", a1, a2) => |
152 case Bop("<", a1, a2) => |
149 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpge $jmp" |
153 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpge $jmp" |
151 |
155 |
152 // statement compilation |
156 // statement compilation |
153 def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { |
157 def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { |
154 case Skip => ("", env) |
158 case Skip => ("", env) |
155 case Assign(x, a) => { |
159 case Assign(x, a) => { |
156 val index = if (env.isDefinedAt(x)) env(x) else env.keys.size |
160 val index = env.getOrElse(x, env.keys.size) |
157 (compile_aexp(a, env) ++ i"istore $index", env + (x -> index)) |
161 (compile_aexp(a, env) ++ i"istore $index \t\t; $x", env + (x -> index)) |
158 } |
162 } |
159 case If(b, bl1, bl2) => { |
163 case If(b, bl1, bl2) => { |
160 val if_else = Fresh("If_else") |
164 val if_else = Fresh("If_else") |
161 val if_end = Fresh("If_end") |
165 val if_end = Fresh("If_end") |
162 val (instrs1, env1) = compile_block(bl1, env) |
166 val (instrs1, env1) = compile_block(bl1, env) |
177 instrs1 ++ |
181 instrs1 ++ |
178 i"goto $loop_begin" ++ |
182 i"goto $loop_begin" ++ |
179 l"$loop_end", env1) |
183 l"$loop_end", env1) |
180 } |
184 } |
181 case Write(x) => |
185 case Write(x) => |
182 (i"iload ${env(x)}" ++ |
186 (i"iload ${env(x)} \t\t; $x" ++ |
183 i"invokestatic XXX/XXX/write(I)V", env) |
187 i"invokestatic XXX/XXX/write(I)V", env) |
184 case Read(x) => { |
188 case Read(x) => { |
185 val index = if (env.isDefinedAt(x)) env(x) else env.keys.size |
189 val index = env.getOrElse(x, env.keys.size) |
186 (i"invokestatic XXX/XXX/read()I" ++ |
190 (i"invokestatic XXX/XXX/read()I" ++ |
187 i"istore $index", env + (x -> index)) |
191 i"istore $index \t\t; $x", env + (x -> index)) |
188 } |
192 } |
189 } |
193 } |
190 |
194 |
191 // compilation of a block (i.e. list of instructions) |
195 // compilation of a block (i.e. list of instructions) |
192 def compile_block(bl: Block, env: Env) : (String, Env) = bl match { |
196 def compile_block(bl: Block, env: Env) : (String, Env) = bl match { |
264 Assign("minus1",Var("temp")), // minus1 := temp; |
268 Assign("minus1",Var("temp")), // minus1 := temp; |
265 Assign("n",Aop("-",Var("n"),Num(1))))), // n := n - 1 }; |
269 Assign("n",Aop("-",Var("n"),Num(1))))), // n := n - 1 }; |
266 Write("minus1")) // write minus1 |
270 Write("minus1")) // write minus1 |
267 |
271 |
268 |
272 |
|
273 // the compiled file as string |
|
274 // |
|
275 //println(compile(fib_test, "fib")) |
|
276 |
|
277 |
269 compile_run(fib_test, "fib") |
278 compile_run(fib_test, "fib") |
270 |
279 |
271 |
280 |