114 // regular expressions for the While language |
117 // regular expressions for the While language |
115 val SYM = RANGE("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_") |
118 val SYM = RANGE("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_") |
116 val DIGIT = RANGE("0123456789") |
119 val DIGIT = RANGE("0123456789") |
117 val ID = SYM ~ (SYM | DIGIT).% |
120 val ID = SYM ~ (SYM | DIGIT).% |
118 val NUM = PLUS(DIGIT) |
121 val NUM = PLUS(DIGIT) |
119 val KEYWORD : Rexp = "if" | "then" | "else" | "read" | "write" | "def" |
122 val KEYWORD : Rexp = "if" | "then" | "else" | "write" | "def" |
120 val SEMI: Rexp = ";" |
123 val SEMI: Rexp = ";" |
121 val COMMA: Rexp = "," |
124 val COMMA: Rexp = "," |
122 val OP: Rexp = ":=" | "==" | "-" | "+" | "*" | "!=" | "<" | ">" | "%" | "=" | "/" |
125 val OP: Rexp = ":=" | "==" | "-" | "+" | "*" | "!=" | "<=" | "=>" | "<" | ">" | "%" | "=" | "/" |
123 val WHITESPACE = PLUS(" " | "\n" | "\t") |
126 val WHITESPACE = PLUS(" " | "\n" | "\t") |
124 val RPAREN: Rexp = ")" |
127 val RPAREN: Rexp = ")" |
125 val LPAREN: Rexp = "(" |
128 val LPAREN: Rexp = "(" |
126 val BEGIN: Rexp = "{" |
|
127 val END: Rexp = "}" |
|
128 val ALL = SYM | DIGIT | OP | " " | ":" | ";" | "\"" | "=" | "," | "(" | ")" |
129 val ALL = SYM | DIGIT | OP | " " | ":" | ";" | "\"" | "=" | "," | "(" | ")" |
129 val ALL2 = ALL | "\n" |
130 val ALL2 = ALL | "\n" |
130 val COMMENT2 = ("/*" ~ NOT(ALL.% ~ "*/" ~ ALL.%) ~ "*/") |
131 //val COMMENT2 = ("/*" ~ NOT(ALL.% ~ "*/" ~ ALL.%) ~ "*/") |
131 val COMMENT = ("/*" ~ ALL2.% ~ "*/") | ("//" ~ ALL.% ~ "\n") |
132 val COMMENT = ("/*" ~ ALL2.% ~ "*/") | ("//" ~ ALL.% ~ "\n") |
132 val STRING = "\"" ~ ALL.% ~ "\"" |
133 |
133 |
134 |
134 |
135 // token for While language |
135 // token for While languag |
|
136 abstract class Token |
136 abstract class Token |
137 case object T_WHITESPACE extends Token |
137 case object T_WHITESPACE extends Token |
138 case object T_SEMI extends Token |
138 case object T_SEMI extends Token |
139 case object T_COMMA extends Token |
139 case object T_COMMA extends Token |
140 case object T_LPAREN extends Token |
140 case object T_LPAREN extends Token |
141 case object T_RPAREN extends Token |
141 case object T_RPAREN extends Token |
142 case object T_BEGIN extends Token |
|
143 case object T_END extends Token |
|
144 case object T_COMMENT extends Token |
142 case object T_COMMENT extends Token |
145 case class T_ID(s: String) extends Token |
143 case class T_ID(s: String) extends Token |
146 case class T_OP(s: String) extends Token |
144 case class T_OP(s: String) extends Token |
147 case class T_NUM(s: String) extends Token |
145 case class T_NUM(s: String) extends Token |
148 case class T_KWD(s: String) extends Token |
146 case class T_KWD(s: String) extends Token |
149 case class T_STRING(s: String) extends Token |
|
150 case class T_ERR(s: String) extends Token // special error token |
147 case class T_ERR(s: String) extends Token // special error token |
151 |
148 |
152 |
149 |
153 type TokenFun = String => Token |
150 type TokenFun = String => Token |
154 type LexRules = List[(Rexp, TokenFun)] |
151 type LexRules = List[(Rexp, TokenFun)] |
221 case class Def(name: String, args: List[String], body: Exp) extends Decl |
208 case class Def(name: String, args: List[String], body: Exp) extends Decl |
222 case class Main(e: Exp) extends Decl |
209 case class Main(e: Exp) extends Decl |
223 |
210 |
224 case class Call(name: String, args: List[Exp]) extends Exp |
211 case class Call(name: String, args: List[Exp]) extends Exp |
225 case class If(a: BExp, e1: Exp, e2: Exp) extends Exp |
212 case class If(a: BExp, e1: Exp, e2: Exp) extends Exp |
226 case class Read(s: String) extends Exp |
213 case class Write(e: Exp) extends Exp |
227 case class Write(s: String) extends Exp |
|
228 case class WriteS(s: String) extends Exp |
|
229 case class Var(s: String) extends Exp |
214 case class Var(s: String) extends Exp |
230 case class Num(i: Int) extends Exp |
215 case class Num(i: Int) extends Exp |
231 case class Aop(o: String, a1: Exp, a2: Exp) extends Exp |
216 case class Aop(o: String, a1: Exp, a2: Exp) extends Exp |
232 |
217 case class Sequ(e1: Exp, e2: Exp) extends Exp |
233 case object True extends BExp |
218 |
234 case object False extends BExp |
|
235 case class Bop(o: String, a1: Exp, a2: Exp) extends BExp |
219 case class Bop(o: String, a1: Exp, a2: Exp) extends BExp |
|
220 |
|
221 // calculating the maximal needed stack size |
|
222 def max_stack_exp(e: Exp): Int = e match { |
|
223 case Call(_, args) => args.map(max_stack_exp).sum |
|
224 case If(a, e1, e2) => max_stack_bexp(a) + (List(max_stack_exp(e1), max_stack_exp(e1)).max) |
|
225 case Write(e) => max_stack_exp(e) + 1 |
|
226 case Var(_) => 1 |
|
227 case Num(_) => 1 |
|
228 case Aop(_, a1, a2) => max_stack_exp(a1) + max_stack_exp(a2) |
|
229 case Sequ(e1, e2) => List(max_stack_exp(e1), max_stack_exp(e2)).max |
|
230 } |
|
231 def max_stack_bexp(e: BExp): Int = e match { |
|
232 case Bop(_, a1, a2) => max_stack_exp(a1) + max_stack_exp(a2) |
|
233 } |
|
234 |
|
235 |
236 |
236 |
237 // Parser combinators |
237 // Parser combinators |
238 abstract class Parser[I <% Seq[_], T] { |
238 abstract class Parser[I <% Seq[_], T] { |
239 def parse(ts: I): Set[(T, I)] |
239 def parse(ts: I): Set[(T, I)] |
240 |
240 |
307 (p ~ q ~ ListParser(p, q)) ==> { case ((x, y), z) => x :: z : List[T] } || |
301 (p ~ q ~ ListParser(p, q)) ==> { case ((x, y), z) => x :: z : List[T] } || |
308 (p ==> ((s) => List(s))) |
302 (p ==> ((s) => List(s))) |
309 } |
303 } |
310 |
304 |
311 |
305 |
312 // arithmetic expressions |
306 // expressions |
313 lazy val Exp: Parser[List[Token], Exp] = |
307 lazy val Exp: Parser[List[Token], Exp] = |
314 (IdParser ~ T_LPAREN ~ ListParser(Exp, T_COMMA) ~ T_RPAREN) ==> |
|
315 { case (((x, y), z), w) => Call(x, z): Exp } || |
|
316 (T_KWD("if") ~ BExp ~ T_KWD("then") ~ Exp ~ T_KWD("else") ~ Exp) ==> |
308 (T_KWD("if") ~ BExp ~ T_KWD("then") ~ Exp ~ T_KWD("else") ~ Exp) ==> |
317 { case (((((x, y), z), u), v), w) => If(y, u, w): Exp } || |
309 { case (((((x, y), z), u), v), w) => If(y, u, w): Exp } || |
|
310 (M ~ T_SEMI ~ Exp) ==> { case ((x, y), z) => Sequ(x, z): Exp } || M |
|
311 lazy val M: Parser[List[Token], Exp] = |
|
312 (T_KWD("write") ~ L) ==> { case (x, y) => Write(y): Exp } || L |
|
313 lazy val L: Parser[List[Token], Exp] = |
318 (T ~ T_OP("+") ~ Exp) ==> { case ((x, y), z) => Aop("+", x, z): Exp } || |
314 (T ~ T_OP("+") ~ Exp) ==> { case ((x, y), z) => Aop("+", x, z): Exp } || |
319 (T ~ T_OP("-") ~ Exp) ==> { case ((x, y), z) => Aop("-", x, z): Exp } || T |
315 (T ~ T_OP("-") ~ Exp) ==> { case ((x, y), z) => Aop("-", x, z): Exp } || T |
320 lazy val T: Parser[List[Token], Exp] = |
316 lazy val T: Parser[List[Token], Exp] = |
321 (F ~ T_OP("*") ~ T) ==> { case ((x, y), z) => Aop("*", x, z): Exp } || |
317 (F ~ T_OP("*") ~ T) ==> { case ((x, y), z) => Aop("*", x, z): Exp } || |
322 (F ~ T_OP("/") ~ T) ==> { case ((x, y), z) => Aop("/", x, z): Exp } || |
318 (F ~ T_OP("/") ~ T) ==> { case ((x, y), z) => Aop("/", x, z): Exp } || |
323 (F ~ T_OP("%") ~ T) ==> { case ((x, y), z) => Aop("%", x, z): Exp } || F |
319 (F ~ T_OP("%") ~ T) ==> { case ((x, y), z) => Aop("%", x, z): Exp } || F |
324 lazy val F: Parser[List[Token], Exp] = |
320 lazy val F: Parser[List[Token], Exp] = |
|
321 (IdParser ~ T_LPAREN ~ ListParser(Exp, T_COMMA) ~ T_RPAREN) ==> |
|
322 { case (((x, y), z), w) => Call(x, z): Exp } || |
325 (T_LPAREN ~ Exp ~ T_RPAREN) ==> { case ((x, y), z) => y: Exp } || |
323 (T_LPAREN ~ Exp ~ T_RPAREN) ==> { case ((x, y), z) => y: Exp } || |
326 IdParser ==> { case x => Var(x): Exp } || |
324 IdParser ==> { case x => Var(x): Exp } || |
327 NumParser ==> { case x => Num(x): Exp } |
325 NumParser ==> { case x => Num(x): Exp } |
328 |
326 |
329 // boolean expressions |
327 // boolean expressions |
330 lazy val BExp: Parser[List[Token], BExp] = |
328 lazy val BExp: Parser[List[Token], BExp] = |
331 (Exp ~ T_OP("==") ~ Exp) ==> { case ((x, y), z) => Bop("==", x, z): BExp } || |
329 (Exp ~ T_OP("==") ~ Exp) ==> { case ((x, y), z) => Bop("==", x, z): BExp } || |
332 (Exp ~ T_OP("!=") ~ Exp) ==> { case ((x, y), z) => Bop("!=", x, z): BExp } || |
330 (Exp ~ T_OP("!=") ~ Exp) ==> { case ((x, y), z) => Bop("!=", x, z): BExp } || |
333 (Exp ~ T_OP("<") ~ Exp) ==> { case ((x, y), z) => Bop("<", x, z): BExp } || |
331 (Exp ~ T_OP("<") ~ Exp) ==> { case ((x, y), z) => Bop("<", x, z): BExp } || |
334 (Exp ~ T_OP(">") ~ Exp) ==> { case ((x, y), z) => Bop("<", z, x): BExp } || |
332 (Exp ~ T_OP(">") ~ Exp) ==> { case ((x, y), z) => Bop("<", z, x): BExp } || |
335 (T_KWD("true") ==> ((_) => True)) || |
333 (Exp ~ T_OP("<=") ~ Exp) ==> { case ((x, y), z) => Bop("<=", x, z): BExp } || |
336 (T_KWD("false") ==> ((_) => False: BExp)) |
334 (Exp ~ T_OP("=>") ~ Exp) ==> { case ((x, y), z) => Bop("<=", z, x): BExp } |
337 |
335 |
338 lazy val Defn: Parser[List[Token], Decl] = |
336 lazy val Defn: Parser[List[Token], Decl] = |
339 (T_KWD("def") ~ IdParser ~ T_LPAREN ~ ListParser(IdParser, T_COMMA) ~ T_RPAREN ~ T_OP("=") ~ Exp) ==> |
337 (T_KWD("def") ~ IdParser ~ T_LPAREN ~ ListParser(IdParser, T_COMMA) ~ T_RPAREN ~ T_OP("=") ~ Exp) ==> |
340 { case ((((((x, y), z), w), u), v), r) => Def(y, w, r): Decl } |
338 { case ((((((x, y), z), w), u), v), r) => Def(y, w, r): Decl } |
341 |
339 |
342 lazy val Prog: Parser[List[Token], List[Decl]] = |
340 lazy val Prog: Parser[List[Token], List[Decl]] = |
343 (Defn ~ T_SEMI ~ Prog) ==> { case ((x, y), z) => x :: z : List[Decl] } || |
341 (Defn ~ T_SEMI ~ Prog) ==> { case ((x, y), z) => x :: z : List[Decl] } || |
344 (Exp ==> ((s) => List(Main(s)) : List[Decl])) |
342 (Exp ==> ((s) => List(Main(s)) : List[Decl])) |
345 |
343 |
346 // parser examples |
344 // parser examples |
347 |
|
348 val p11 = """def zero(x) = 0""" |
|
349 val p11_toks = tokenizer(p11) |
|
350 val p11_ast = Defn.parse_all(p11_toks) |
|
351 //println(p11_toks) |
|
352 //println(p11_ast) |
|
353 |
|
354 |
345 |
355 val p12_toks = tokenizer(fromFile("defs.rec")) |
346 val p12_toks = tokenizer(fromFile("defs.rec")) |
356 val p12_ast = Prog.parse_all(p12_toks) |
347 val p12_ast = Prog.parse_all(p12_toks) |
357 //println(p12_toks.mkString(",")) |
348 //println(p12_toks.mkString(",")) |
358 //println(p12_ast) |
349 //println(p12_ast) |
381 swap |
372 swap |
382 invokevirtual java/io/PrintStream/println(I)V |
373 invokevirtual java/io/PrintStream/println(I)V |
383 return |
374 return |
384 .end method |
375 .end method |
385 |
376 |
386 .method public static writes(Ljava/lang/String;)V |
|
387 .limit stack 2 |
|
388 .limit locals 2 |
|
389 getstatic java/lang/System/out Ljava/io/PrintStream; |
|
390 aload 0 |
|
391 invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V |
|
392 return |
|
393 .end method |
|
394 |
|
395 .method public static read()I |
|
396 .limit locals 10 |
|
397 .limit stack 10 |
|
398 |
|
399 ldc 0 |
|
400 istore 1 ; this will hold our final integer |
|
401 Label1: |
|
402 getstatic java/lang/System/in Ljava/io/InputStream; |
|
403 invokevirtual java/io/InputStream/read()I |
|
404 istore 2 |
|
405 iload 2 |
|
406 ldc 10 ; the newline delimiter |
|
407 isub |
|
408 ifeq Label2 |
|
409 iload 2 |
|
410 ldc 32 ; the space delimiter |
|
411 isub |
|
412 ifeq Label2 |
|
413 |
|
414 iload 2 |
|
415 ldc 48 ; we have our digit in ASCII, have to subtract it from 48 |
|
416 isub |
|
417 ldc 10 |
|
418 iload 1 |
|
419 imul |
|
420 iadd |
|
421 istore 1 |
|
422 goto Label1 |
|
423 Label2: |
|
424 ;when we come here we have our integer computed in Local Variable 1 |
|
425 iload 1 |
|
426 ireturn |
|
427 .end method |
|
428 |
|
429 .method public static main([Ljava/lang/String;)V |
|
430 .limit locals 200 |
|
431 .limit stack 200 |
|
432 |
|
433 """ |
|
434 |
|
435 val ending = """ |
|
436 |
|
437 return |
|
438 |
|
439 .end method |
|
440 """ |
377 """ |
441 |
378 |
442 // for generating new labels |
379 // for generating new labels |
443 var counter = -1 |
380 var counter = -1 |
444 |
381 |
445 def Fresh(x: String) = { |
382 def Fresh(x: String) = { |
446 counter += 1 |
383 counter += 1 |
447 x ++ "_" ++ counter.toString() |
384 x ++ "_" ++ counter.toString() |
448 } |
385 } |
449 |
386 |
450 type Mem = Map[String, String] |
387 type Mem = Map[String, Int] |
451 type Instrs = List[String] |
388 type Instrs = List[String] |
452 |
389 |
453 def compile_exp(a: Exp, env : Mem) : Instrs = a match { |
390 def compile_exp(a: Exp, env : Mem) : Instrs = a match { |
454 case Num(i) => List("ldc " + i.toString + "\n") |
391 case Num(i) => List("ldc " + i.toString + "\n") |
455 case Var(s) => List("iload " + env(s) + "\n") |
392 case Var(s) => List("iload " + env(s).toString + "\n") |
456 case Aop("+", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("iadd\n") |
393 case Aop("+", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("iadd\n") |
457 case Aop("-", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("isub\n") |
394 case Aop("-", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("isub\n") |
458 case Aop("*", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("imul\n") |
395 case Aop("*", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("imul\n") |
|
396 case Aop("/", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("idiv\n") |
|
397 case Aop("%", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("irem\n") |
459 case If(b, a1, a2) => { |
398 case If(b, a1, a2) => { |
460 val if_else = Fresh("If_else") |
399 val if_else = Fresh("If_else") |
461 val if_end = Fresh("If_end") |
400 val if_end = Fresh("If_end") |
462 compile_bexp(b, env, if_else) ++ |
401 compile_bexp(b, env, if_else) ++ |
463 compile_exp(a1, env) ++ |
402 compile_exp(a1, env) ++ |
464 List("goto " + if_end + "\n") ++ |
403 List("goto " + if_end + "\n") ++ |
465 List("\n" + if_else + ":\n\n") ++ |
404 List("\n" + if_else + ":\n\n") ++ |
466 compile_exp(a2, env) ++ |
405 compile_exp(a2, env) ++ |
467 List("\n" + if_end + ":\n\n") |
406 List("\n" + if_end + ":\n\n") |
468 } |
407 } |
469 case Call(n, args) => |
408 case Call(n, args) => { |
|
409 val is = "I" * args.length |
470 args.flatMap(a => compile_exp(a, env)) ++ |
410 args.flatMap(a => compile_exp(a, env)) ++ |
471 List ("invokestatic XXX/XXX/" + n + "(I)I\n") |
411 List ("invokestatic XXX/XXX/" + n + "(" + is + ")I\n") |
472 |
412 } |
|
413 case Sequ(a1, a2) => { |
|
414 compile_exp(a1, env) ++ List("pop\n") ++ compile_exp(a2, env) |
|
415 } |
|
416 case Write(a1) => { |
|
417 compile_exp(a1, env) ++ |
|
418 List("dup\n", |
|
419 "invokestatic XXX/XXX/write(I)V\n") |
|
420 } |
473 } |
421 } |
474 |
422 |
475 def compile_bexp(b: BExp, env : Mem, jmp: String) : Instrs = b match { |
423 def compile_bexp(b: BExp, env : Mem, jmp: String) : Instrs = b match { |
476 case True => Nil |
424 case Bop("==", a1, a2) => |
477 case False => List("goto " + jmp + "\n") |
|
478 case Bop("=", a1, a2) => |
|
479 compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("if_icmpne " + jmp + "\n") |
425 compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("if_icmpne " + jmp + "\n") |
480 case Bop("!=", a1, a2) => |
426 case Bop("!=", a1, a2) => |
481 compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("if_icmpeq " + jmp + "\n") |
427 compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("if_icmpeq " + jmp + "\n") |
482 case Bop("<", a1, a2) => |
428 case Bop("<", a1, a2) => |
483 compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("if_icmpge " + jmp + "\n") |
429 compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("if_icmpge " + jmp + "\n") |
484 } |
430 case Bop("<=", a1, a2) => |
485 |
431 compile_exp(a1, env) ++ compile_exp(a2, env) ++ List("if_icmpgt " + jmp + "\n") |
|
432 } |
|
433 |
|
434 |
|
435 def compile_expT(a: Exp, env : Mem, name: String) : Instrs = a match { |
|
436 case Num(i) => List("ldc " + i.toString + "\n") |
|
437 case Var(s) => List("iload " + env(s).toString + "\n") |
|
438 case Aop("+", a1, a2) => compile_expT(a1, env, "") ++ compile_expT(a2, env, "") ++ List("iadd\n") |
|
439 case Aop("-", a1, a2) => compile_expT(a1, env, "") ++ compile_expT(a2, env, "") ++ List("isub\n") |
|
440 case Aop("*", a1, a2) => compile_expT(a1, env, "") ++ compile_expT(a2, env, "") ++ List("imul\n") |
|
441 case Aop("/", a1, a2) => compile_expT(a1, env, "") ++ compile_expT(a2, env, "") ++ List("idiv\n") |
|
442 case Aop("%", a1, a2) => compile_expT(a1, env, "") ++ compile_expT(a2, env, "") ++ List("irem\n") |
|
443 case If(b, a1, a2) => { |
|
444 val if_else = Fresh("If_else") |
|
445 val if_end = Fresh("If_end") |
|
446 compile_bexp(b, env, if_else) ++ |
|
447 compile_expT(a1, env, name) ++ |
|
448 List("goto " + if_end + "\n") ++ |
|
449 List("\n" + if_else + ":\n\n") ++ |
|
450 compile_expT(a2, env, name) ++ |
|
451 List("\n" + if_end + ":\n\n") |
|
452 } |
|
453 case Call(n, args) => if (name == n) { |
|
454 val stores = args.zipWithIndex.map { case (x, y) => "istore " + y.toString + "\n" } |
|
455 args.flatMap(a => compile_expT(a, env, "")) ++ |
|
456 stores.reverse ++ |
|
457 List ("goto " + n + "_Start\n") |
|
458 } else { |
|
459 val is = "I" * args.length |
|
460 args.flatMap(a => compile_expT(a, env, "")) ++ |
|
461 List ("invokestatic XXX/XXX/" + n + "(" + is + ")I\n") |
|
462 } |
|
463 case Sequ(a1, a2) => { |
|
464 compile_expT(a1, env, "") ++ List("pop\n") ++ compile_expT(a2, env, name) |
|
465 } |
|
466 case Write(a1) => { |
|
467 compile_expT(a1, env, "") ++ |
|
468 List("dup\n", |
|
469 "invokestatic XXX/XXX/write(I)V\n") |
|
470 } |
|
471 } |
|
472 |
|
473 def compile_bexpT(b: BExp, env : Mem, jmp: String) : Instrs = b match { |
|
474 case Bop("==", a1, a2) => |
|
475 compile_expT(a1, env, "") ++ compile_expT(a2, env, "") ++ List("if_icmpne " + jmp + "\n") |
|
476 case Bop("!=", a1, a2) => |
|
477 compile_expT(a1, env, "") ++ compile_expT(a2, env, "") ++ List("if_icmpeq " + jmp + "\n") |
|
478 case Bop("<", a1, a2) => |
|
479 compile_expT(a1, env, "") ++ compile_expT(a2, env, "") ++ List("if_icmpge " + jmp + "\n") |
|
480 case Bop("<=", a1, a2) => |
|
481 compile_expT(a1, env, "") ++ compile_expT(a2, env, "") ++ List("if_icmpgt " + jmp + "\n") |
|
482 } |
486 |
483 |
487 |
484 |
488 def compile_decl(d: Decl) : Instrs = d match { |
485 def compile_decl(d: Decl) : Instrs = d match { |
489 case Def(name, args, a) => Nil |
486 case Def(name, args, a) => { |
490 case Main(a) => compile_exp(a, Map()) |
487 val env = args.zipWithIndex.toMap |
|
488 val is = "I" * args.length |
|
489 List(".method public static " + name + "(" + is + ")I \n", |
|
490 ".limit locals " + args.length.toString + "\n", |
|
491 ".limit stack " + (1 + max_stack_exp(a)).toString + "\n", |
|
492 name + "_Start:\n") ++ |
|
493 //compile_exp(a, env) ++ |
|
494 compile_expT(a, env, name) ++ |
|
495 List("ireturn\n", |
|
496 ".end method \n\n") |
|
497 } |
|
498 case Main(a) => { |
|
499 val main_begin = |
|
500 List(".method public static main([Ljava/lang/String;)V\n", |
|
501 ".limit locals 200\n", |
|
502 ".limit stack 200\n") |
|
503 val main_end = |
|
504 List("invokestatic XXX/XXX/write(I)V\n", |
|
505 "return\n", |
|
506 ".end method\n") |
|
507 main_begin ++ compile_exp(a, Map()) ++ main_end |
|
508 } |
491 } |
509 } |
492 |
510 |
493 def compile(class_name: String, input: String) : String = { |
511 def compile(class_name: String, input: String) : String = { |
494 val tks = tokenizer(input) |
512 val tks = tokenizer(input) |
|
513 //println(Prog.parse(tks)) |
495 val ast = Prog.parse_single(tks) |
514 val ast = Prog.parse_single(tks) |
496 val instructions = ast.flatMap(compile_decl).mkString |
515 val instructions = ast.flatMap(compile_decl).mkString |
497 (instructions).replaceAllLiterally("XXX", class_name) |
516 (library + instructions).replaceAllLiterally("XXX", class_name) |
498 } |
517 } |
499 |
518 |
500 |
519 |
501 def compile_file(file_name: String) = { |
520 def compile_file(file_name: String) = { |
502 val class_name = file_name.split('.')(0) |
521 val class_name = file_name.split('.')(0) |