progs/compile.scala
changeset 687 8865f4f2be59
parent 674 e0a41a1f24cf
child 690 8d57433c7b5e
equal deleted inserted replaced
686:05cfce0fdef7 687:8865f4f2be59
   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