99 case "+" => i"iadd" |
103 case "+" => i"iadd" |
100 case "-" => i"isub" |
104 case "-" => i"isub" |
101 case "*" => i"imul" |
105 case "*" => i"imul" |
102 } |
106 } |
103 |
107 |
104 def compile_num(i: Int) = |
|
105 if (0 <= i && i <= 5) i"iconst_$i" else i"ldc $i" |
|
106 |
|
107 def compile_aload(i: Int) = |
|
108 if (0 <= i && i <= 3) i"aload_$i" else i"aload $i" |
|
109 |
|
110 def compile_iload(i: Int) = |
|
111 if (0 <= i && i <= 3) i"iload_$i" else i"iload $i" |
|
112 |
|
113 def compile_istore(i: Int) = |
|
114 if (0 <= i && i <= 3) i"istore_$i" else i"istore $i" |
|
115 |
|
116 // arithmetic expression compilation |
108 // arithmetic expression compilation |
117 def compile_aexp(a: AExp, env : Env) : String = a match { |
109 def compile_aexp(a: AExp, env : Env) : String = a match { |
118 case Num(i) => compile_num(i) |
110 case Num(i) => i"ldc $i" |
119 case Var(s) => compile_iload(env(s)) |
111 case Var(s) => i"iload ${env(s)}" |
120 case Aop(op, a1, a2) => |
112 case Aop(op, a1, a2) => |
121 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op) |
113 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op) |
122 case Ref(s, a) => |
114 case Ref(s, a) => |
123 compile_aload(env(s)) ++ compile_aexp(a, env) ++ i"iaload" |
115 i"aload ${env(s)}" ++ compile_aexp(a, env) ++ i"iaload" |
124 } |
116 } |
125 |
|
126 def compile_bop(op: String, jmp: String) = op match { |
|
127 case "==" => i"if_icmpne $jmp" |
|
128 case "!=" => i"if_icmpeq $jmp" |
|
129 case "<" => i"if_icmpge $jmp" |
|
130 } |
|
131 |
|
132 |
117 |
133 // boolean expression compilation |
118 // boolean expression compilation |
134 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match { |
119 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match { |
135 case True => "" |
120 case True => "" |
136 case False => i"goto $jmp" |
121 case False => i"goto $jmp" |
137 case Bop(op, a1, a2) => |
122 case Bop("==", a1, a2) => |
138 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_bop(op, jmp) |
123 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpne $jmp" |
|
124 case Bop("!=", a1, a2) => |
|
125 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpeq $jmp" |
|
126 case Bop("<", a1, a2) => |
|
127 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpge $jmp" |
139 } |
128 } |
140 |
129 |
141 // statement compilation |
130 // statement compilation |
142 def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { |
131 def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { |
143 case Skip => ("", env) |
132 case Skip => ("", env) |
144 case Assign(x, a) => { |
133 case Assign(x, a) => { |
145 val index = env.getOrElse(x, env.keys.size) // |
134 val index = env.getOrElse(x, env.keys.size) |
146 (compile_aexp(a, env) ++ compile_istore(index), env + (x -> index)) |
135 (compile_aexp(a, env) ++ i"istore $index \t\t; $x", env + (x -> index)) |
147 } |
136 } |
148 case If(b, bl1, bl2) => { |
137 case If(b, bl1, bl2) => { |
149 val if_else = Fresh("If_else") |
138 val if_else = Fresh("If_else") |
150 val if_end = Fresh("If_end") |
139 val if_end = Fresh("If_end") |
151 val (instrs1, env1) = compile_block(bl1, env) |
140 val (instrs1, env1) = compile_block(bl1, env) |
166 instrs1 ++ |
155 instrs1 ++ |
167 i"goto $loop_begin" ++ |
156 i"goto $loop_begin" ++ |
168 l"$loop_end", env1) |
157 l"$loop_end", env1) |
169 } |
158 } |
170 case Write(x) => |
159 case Write(x) => |
171 (compile_iload(env(x)) ++ |
160 (i"iload ${env(x)} \t\t; $x" ++ |
172 i"invokestatic XXX/XXX/write(I)V", env) |
161 i"invokestatic XXX/XXX/write(I)V", env) |
173 case Read(x) => { |
162 case Read(x) => { |
174 val index = env.getOrElse(x, env.keys.size) |
163 val index = env.getOrElse(x, env.keys.size) |
175 (i"invokestatic XXX/XXX/read()I" ++ |
164 (i"invokestatic XXX/XXX/read()I" ++ |
176 compile_istore(index), env + (x -> index)) |
165 i"istore $index \t\t; $x", env + (x -> index)) |
177 } |
166 } |
178 case ArrayDef(s: String, n: Int) => { |
167 case ArrayDef(s: String, n: Int) => { |
179 val index = if (env.isDefinedAt(s)) throw new Exception("array def error") else |
168 val index = if (env.isDefinedAt(s)) throw new Exception("array def error") else |
180 env.keys.size |
169 env.keys.size |
181 (i"ldc $n" ++ |
170 (i"ldc $n" ++ |
183 i"astore $index", env + (s -> index)) |
172 i"astore $index", env + (s -> index)) |
184 } |
173 } |
185 case AssignA(s, a1, a2) => { |
174 case AssignA(s, a1, a2) => { |
186 val index = if (env.isDefinedAt(s)) env(s) else |
175 val index = if (env.isDefinedAt(s)) env(s) else |
187 throw new Exception("array not defined") |
176 throw new Exception("array not defined") |
188 (compile_aload(env(s)) ++ |
177 (i"aload ${env(s)}" ++ |
189 compile_aexp(a1, env) ++ |
178 compile_aexp(a1, env) ++ |
190 compile_aexp(a2, env) ++ |
179 compile_aexp(a2, env) ++ |
191 i"iastore", env) |
180 i"iastore", env) |
192 } |
181 } |
193 } |
182 } |
376 ("if" ~ BExp ~ "then" ~ Block ~ "else" ~ Block) ==> |
365 ("if" ~ BExp ~ "then" ~ Block ~ "else" ~ Block) ==> |
377 { case _ ~ y ~ _ ~ u ~ _ ~w => If(y, u, w): Stmt } | |
366 { case _ ~ y ~ _ ~ u ~ _ ~w => If(y, u, w): Stmt } | |
378 ("while" ~ BExp ~ "do" ~ Block) ==> { case _ ~ y ~ _ ~ w => While(y, w) } | |
367 ("while" ~ BExp ~ "do" ~ Block) ==> { case _ ~ y ~ _ ~ w => While(y, w) } | |
379 ("new(" ~ IdParser ~ "[" ~ NumParser ~ "])") ==> { |
368 ("new(" ~ IdParser ~ "[" ~ NumParser ~ "])") ==> { |
380 case _ ~ y ~ _ ~ u ~ _ => ArrayDef(y, u) } | |
369 case _ ~ y ~ _ ~ u ~ _ => ArrayDef(y, u) } | |
381 ("write" ~ IdParser) ==> { case _ ~ y => Write(y) } |
370 ("write(" ~ IdParser ~ ")") ==> { case _ ~ y ~ _ => Write(y) } |
382 |
371 |
383 lazy val Stmts: Parser[String, Block] = |
372 lazy val Stmts: Parser[String, Block] = |
384 (Stmt ~ ";" ~ Stmts) ==> { case x ~ _ ~ z => x :: z : Block } | |
373 (Stmt ~ ";" ~ Stmts) ==> { case x ~ _ ~ z => x :: z : Block } | |
385 (Stmt ==> ((s) => List(s) : Block)) |
374 (Stmt ==> ((s) => List(s) : Block)) |
386 |
375 |