progs/while/compile.sc
author Christian Urban <christian.urban@kcl.ac.uk>
Fri, 24 Sep 2021 23:56:31 +0100
changeset 839 7af70f9b30ab
parent 828 bdcaecdee9eb
child 943 5365ef60707e
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
     1
// A Small Compiler for the WHILE Language
674
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
     2
// (it does not use a parser nor lexer)
790
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
     3
//
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
     4
// cal with 
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
     5
//
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
     6
//   amm compile.sc test
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
     7
//   amm compile.sc test2
69
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
     8
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
     9
69
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    10
// the abstract syntax trees
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    11
abstract class Stmt
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    12
abstract class AExp
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    13
abstract class BExp 
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    14
type Block = List[Stmt]
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
    15
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
    16
// statements
69
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    17
case object Skip extends Stmt
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    18
case class If(a: BExp, bl1: Block, bl2: Block) extends Stmt
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    19
case class While(b: BExp, bl: Block) extends Stmt
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    20
case class Assign(s: String, a: AExp) extends Stmt
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    21
case class Write(s: String) extends Stmt
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
    22
case class Read(s: String) extends Stmt
70
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 69
diff changeset
    23
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
    24
// arithmetic expressions
69
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    25
case class Var(s: String) extends AExp
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    26
case class Num(i: Int) extends AExp
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    27
case class Aop(o: String, a1: AExp, a2: AExp) extends AExp
70
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 69
diff changeset
    28
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
    29
// boolean expressions
69
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    30
case object True extends BExp
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    31
case object False extends BExp
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
    32
case class Bop(o: String, a1: AExp, a2: AExp) extends BExp
66
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    33
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    34
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
    35
// compiler headers needed for the JVM
695
484b74bc057e deleted init function from boilerplate code
Christian Urban <urbanc@in.tum.de>
parents: 690
diff changeset
    36
// (contains methods for read and write)
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    37
val beginning = """
80
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 76
diff changeset
    38
.class public XXX.XXX
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    39
.super java/lang/Object
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    40
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    41
.method public static write(I)V 
373
b018234c9126 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 369
diff changeset
    42
    .limit locals 1 
b018234c9126 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 369
diff changeset
    43
    .limit stack 2 
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    44
    getstatic java/lang/System/out Ljava/io/PrintStream; 
373
b018234c9126 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 369
diff changeset
    45
    iload 0
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    46
    invokevirtual java/io/PrintStream/println(I)V 
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    47
    return 
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    48
.end method
69
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    49
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    50
.method public static main([Ljava/lang/String;)V
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    51
   .limit locals 200
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    52
   .limit stack 200
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    53
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    54
; COMPILED CODE STARTS
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    55
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    56
"""
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    57
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    58
val ending = """
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    59
; COMPILED CODE ENDS
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    60
   return
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    61
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    62
.end method
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    63
"""
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    64
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    65
// Compiler functions
471
9476086849ad updated
Christian Urban <urbanc@in.tum.de>
parents: 373
diff changeset
    66
9476086849ad updated
Christian Urban <urbanc@in.tum.de>
parents: 373
diff changeset
    67
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    68
// for generating new labels
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    69
var counter = -1
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    70
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    71
def Fresh(x: String) = {
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    72
  counter += 1
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    73
  x ++ "_" ++ counter.toString()
66
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    74
}
69
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
    75
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    76
// convenient string interpolations 
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    77
// for instructions and labels
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    78
import scala.language.implicitConversions
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    79
import scala.language.reflectiveCalls
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    80
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    81
implicit def sring_inters(sc: StringContext) = new {
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    82
    def i(args: Any*): String = "   " ++ sc.s(args:_*) ++ "\n"
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    83
    def l(args: Any*): String = sc.s(args:_*) ++ ":\n"
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    84
}
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    85
716
df7d47a507f8 updated
Christian Urban <urbanc@in.tum.de>
parents: 695
diff changeset
    86
// this allows us to write things like
809
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
    87
// i"iadd" and l"Label"
687
8865f4f2be59 updated
Christian Urban <urbanc@in.tum.de>
parents: 674
diff changeset
    88
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    89
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
    90
// environments 
668
9ce78065f68d updated
Christian Urban <urbanc@in.tum.de>
parents: 625
diff changeset
    91
type Env = Map[String, Int]
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
    92
674
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
    93
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
    94
def compile_op(op: String) = op match {
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
    95
  case "+" => i"iadd"
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
    96
  case "-" => i"isub"
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
    97
  case "*" => i"imul"
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
    98
}
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
    99
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   100
// arithmetic expression compilation
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   101
def compile_aexp(a: AExp, env : Env) : String = a match {
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   102
  case Num(i) => i"ldc $i"
687
8865f4f2be59 updated
Christian Urban <urbanc@in.tum.de>
parents: 674
diff changeset
   103
  case Var(s) => i"iload ${env(s)} \t\t; $s"
674
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
   104
  case Aop(op, a1, a2) => 
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
   105
    compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op)
69
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
   106
}
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
   107
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   108
// boolean expression compilation
687
8865f4f2be59 updated
Christian Urban <urbanc@in.tum.de>
parents: 674
diff changeset
   109
//  - the jump-label is for where to jump if the condition is not true
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   110
def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match {
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   111
  case True => ""
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   112
  case False => i"goto $jmp"
687
8865f4f2be59 updated
Christian Urban <urbanc@in.tum.de>
parents: 674
diff changeset
   113
  case Bop("==", a1, a2) => 
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   114
    compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpne $jmp"
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   115
  case Bop("!=", a1, a2) => 
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   116
    compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpeq $jmp"
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   117
  case Bop("<", a1, a2) => 
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   118
    compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpge $jmp"
69
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
   119
}
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
   120
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   121
// statement compilation
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   122
def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match {
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   123
  case Skip => ("", env)
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   124
  case Assign(x, a) => {
687
8865f4f2be59 updated
Christian Urban <urbanc@in.tum.de>
parents: 674
diff changeset
   125
    val index = env.getOrElse(x, env.keys.size)
8865f4f2be59 updated
Christian Urban <urbanc@in.tum.de>
parents: 674
diff changeset
   126
    (compile_aexp(a, env) ++ i"istore $index \t\t; $x", env + (x -> index))
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   127
  } 
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   128
  case If(b, bl1, bl2) => {
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   129
    val if_else = Fresh("If_else")
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   130
    val if_end = Fresh("If_end")
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   131
    val (instrs1, env1) = compile_block(bl1, env)
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   132
    val (instrs2, env2) = compile_block(bl2, env1)
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   133
    (compile_bexp(b, env, if_else) ++
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   134
     instrs1 ++
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   135
     i"goto $if_end" ++
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   136
     l"$if_else" ++
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   137
     instrs2 ++
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   138
     l"$if_end", env2)
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   139
  }
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   140
  case While(b, bl) => {
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   141
    val loop_begin = Fresh("Loop_begin")
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   142
    val loop_end = Fresh("Loop_end")
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   143
    val (instrs1, env1) = compile_block(bl, env)
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   144
    (l"$loop_begin" ++
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   145
     compile_bexp(b, env, loop_end) ++
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   146
     instrs1 ++
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   147
     i"goto $loop_begin" ++
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   148
     l"$loop_end", env1)
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   149
  }
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   150
  case Write(x) => 
687
8865f4f2be59 updated
Christian Urban <urbanc@in.tum.de>
parents: 674
diff changeset
   151
    (i"iload ${env(x)} \t\t; $x" ++ 
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   152
     i"invokestatic XXX/XXX/write(I)V", env)
811
86406d70d6f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 810
diff changeset
   153
  //case Read(x) => {
86406d70d6f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 810
diff changeset
   154
  //  val index = env.getOrElse(x, env.keys.size) 
86406d70d6f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 810
diff changeset
   155
  //  (i"invokestatic XXX/XXX/read()I" ++ 
86406d70d6f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 810
diff changeset
   156
  //   i"istore $index \t\t; $x", env + (x -> index))
86406d70d6f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 810
diff changeset
   157
  //}
69
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
   158
}
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 68
diff changeset
   159
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   160
// compilation of a block (i.e. list of instructions)
624
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   161
def compile_block(bl: Block, env: Env) : (String, Env) = bl match {
8d0af38389bc updated to Scala 2.13
Christian Urban <urbanc@in.tum.de>
parents: 609
diff changeset
   162
  case Nil => ("", env)
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   163
  case s::bl => {
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   164
    val (instrs1, env1) = compile_stmt(s, env)
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   165
    val (instrs2, env2) = compile_block(bl, env1)
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   166
    (instrs1 ++ instrs2, env2)
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   167
  }
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   168
}
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   169
323
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   170
// main compilation function for blocks
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   171
def compile(bl: Block, class_name: String) : String = {
4ce07c4abdb4 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 201
diff changeset
   172
  val instructions = compile_block(bl, Map.empty)._1
690
8d57433c7b5e updated
Christian Urban <urbanc@in.tum.de>
parents: 687
diff changeset
   173
  (beginning ++ instructions ++ ending).replaceAllLiterally("XXX", class_name)
76
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   174
}
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   175
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   176
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 75
diff changeset
   177
609
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   178
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   179
674
e0a41a1f24cf updated
Christian Urban <urbanc@in.tum.de>
parents: 668
diff changeset
   180
// Fibonacci numbers as a bare-bone test-case
609
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   181
val fib_test = 
811
86406d70d6f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 810
diff changeset
   182
  List(Assign("n", Num(9)),            //  n := 9;                     
609
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   183
       Assign("minus1",Num(0)),         //  minus1 := 0;
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   184
       Assign("minus2",Num(1)),         //  minus2 := 1;
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   185
       Assign("temp",Num(0)),           //  temp := 0;
811
86406d70d6f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 810
diff changeset
   186
       While(Bop("<",Num(0),Var("n")),  //  while 0 < n do  {
625
6709fa87410b updated to 2.13
Christian Urban <urbanc@in.tum.de>
parents: 624
diff changeset
   187
          List(Assign("temp",Var("minus2")), //  temp := minus2;
609
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   188
               Assign("minus2",Aop("+",Var("minus1"),Var("minus2"))), 
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   189
                                        //  minus2 := minus1 + minus2;
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   190
               Assign("minus1",Var("temp")), //  minus1 := temp;
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   191
               Assign("n",Aop("-",Var("n"),Num(1))))), //  n := n - 1 };
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   192
       Write("minus1"))                 //  write minus1
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   193
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   194
790
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   195
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   196
// prints out the JVM instructions
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   197
@main
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   198
def test() = 
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   199
  println(compile(fib_test, "fib"))
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   200
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   201
687
8865f4f2be59 updated
Christian Urban <urbanc@in.tum.de>
parents: 674
diff changeset
   202
8865f4f2be59 updated
Christian Urban <urbanc@in.tum.de>
parents: 674
diff changeset
   203
812
2f9a0dcf61ae updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 811
diff changeset
   204
790
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   205
// compiling and running .j-files
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   206
//
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   207
// JVM files can be assembled with 
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   208
//
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   209
//    java -jar jasmin.jar fib.j
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   210
//
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   211
// and started with
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   212
//
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   213
//    java fib/fib
609
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   214
e33545bb2eba updated
Christian Urban <urbanc@in.tum.de>
parents: 600
diff changeset
   215
790
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   216
def run(bl: Block, class_name: String) = {
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   217
    val code = compile(bl, class_name)
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   218
    os.write.over(os.pwd / s"$class_name.j", code)
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   219
    os.proc("java", "-jar", "jasmin.jar", s"$class_name.j").call()
815
f56d18757526 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 812
diff changeset
   220
    os.proc("java", s"$class_name/$class_name").call(stdout = os.Inherit, stdin = os.Inherit)
790
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   221
}
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   222
816
2b6e23985982 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 815
diff changeset
   223
790
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   224
@main
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   225
def test2() =
31a9f89776a3 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 716
diff changeset
   226
  run(fib_test, "fib")
809
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   227
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   228
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   229
/* Jasmin code for reading an integer
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   230
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   231
.method public static read()I 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   232
    .limit locals 10 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   233
    .limit stack 10
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   234
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   235
    ldc 0 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   236
    istore 1  ; this will hold our final integer 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   237
Label1: 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   238
    getstatic java/lang/System/in Ljava/io/InputStream; 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   239
    invokevirtual java/io/InputStream/read()I 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   240
    istore 2 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   241
    iload 2 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   242
    ldc 10   ; the newline delimiter 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   243
    isub 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   244
    ifeq Label2 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   245
    iload 2 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   246
    ldc 32   ; the space delimiter 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   247
    isub 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   248
    ifeq Label2
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   249
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   250
    iload 2 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   251
    ldc 48   ; we have our digit in ASCII, have to subtract it from 48 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   252
    isub 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   253
    ldc 10 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   254
    iload 1 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   255
    imul 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   256
    iadd 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   257
    istore 1 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   258
    goto Label1 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   259
Label2: 
828
bdcaecdee9eb updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 816
diff changeset
   260
    ; when we come here we have our integer computed in local variable 1 
809
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   261
    iload 1 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   262
    ireturn 
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   263
.end method
2b9956d29038 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 790
diff changeset
   264
812
2f9a0dcf61ae updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 811
diff changeset
   265
*/
828
bdcaecdee9eb updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 816
diff changeset
   266
bdcaecdee9eb updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 816
diff changeset
   267
bdcaecdee9eb updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 816
diff changeset
   268
bdcaecdee9eb updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 816
diff changeset
   269
bdcaecdee9eb updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 816
diff changeset
   270
bdcaecdee9eb updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 816
diff changeset
   271
// runs with amm2 and amm3