Guest User

Untitled

a guest
Jul 13th, 2018
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 4.77 KB | None | 0 0
  1. abstract class Instruction
  2. // push operand on the stack
  3. case class Push(v: Int) extends Instruction
  4. // store the operand on the stack in the memory under the given name
  5. case class Store(s: String) extends Instruction
  6. // load a variable from the memory and push it on the operand stack
  7. case class Load(s: String) extends Instruction
  8. // add the first two operands on the stack and push the result on the stack
  9. case class Plus extends Instruction
  10. // subtract the second operand on the stack from the first operand on the stack and push the result on the stack
  11. case class Minus extends Instruction
  12. // multiply the first two operands on the stack and push the result on the stack
  13. case class Times extends Instruction
  14. // pushes a 1 on the stack if the first two operands on the stack are equal, 0 otherwise
  15. case class Equal extends Instruction
  16. // pushes a 1 on the stack if the first operand on the stack is strictly smaller than the second operand on the stack, 0 otherwise
  17. case class LessThan extends Instruction
  18. // marks the current position with the given label. does not modify the operand stack. does not perform any computation
  19. case class Label(s: String) extends Instruction
  20. // performs a jump to the given label
  21. case class Jump(s: String) extends Instruction
  22. // performs a conditional jump. Jumps to the given label if the first operand on the stack is 1
  23. case class CJump(s: String) extends Instruction
  24.  
  25. abstract class Exp
  26. case class Block(es: Exp*) extends Exp
  27. case class Num(v: Int) extends Exp
  28. case class Var(n: String) extends Exp
  29. case class Add(l: Exp, r: Exp) extends Exp
  30. case class Sub(l: Exp, r: Exp) extends Exp
  31. case class Mul(l: Exp, r: Exp) extends Exp
  32. case class Lt(l: Exp, r: Exp) extends Exp
  33. case class Assign(n: String, e: Exp) extends Exp
  34. case class While(c: Exp, body: Exp) extends Exp
  35. case class IfThenElse(c: Exp, t: Exp, e: Exp) extends Exp
  36. case class Repeat(body: Exp, c: Exp) extends Exp
  37.  
  38. object CalculonCompiler {
  39.  
  40.   import scala.collection.mutable.HashMap
  41.  
  42.   // automatically converts instances of Instruction to a List[Instruction] such that one can easily
  43.   // use the ++ operator to append single instructions
  44.   implicit def instrToList(instr: Instruction): List[Instruction] = List(instr)
  45.  
  46.   // counter for unique indexes used for unique variable names
  47.   var uniqueIndex = 0
  48.   // a map to remember renamed variables and their new unique names
  49.   val renames = HashMap[String, String]()
  50.  
  51.   // return a unique String everytime it is called. Useful for label names
  52.   def uniqueName(): String = { uniqueIndex += 1; "name_" + uniqueIndex }
  53.  
  54.   // renames the variable to a unique name if it has not already been renamed. If it has been renamed returns its new unique name.
  55.   // renaming variables is necessary to avoid conflicts between variable names and label names
  56.   def renameVariable(n: String): String = {
  57.     renames.get(n) match {
  58.       case Some(nn) => nn
  59.       case None =>
  60.         val nn = uniqueName()
  61.         renames += (n -> nn)
  62.         nn
  63.     }
  64.   }
  65.  
  66.   // compile with var-args for convenience. dispatches calls to singular expression compile
  67.   def compile(es: Exp*): List[Instruction] = es.foldLeft(List[Instruction]())((l, r) => l ++ compile(r))
  68.  
  69.   // translates the given expression in Calculon to equivalent instructions in the Stackon language
  70.   def compile(e: Exp): List[Instruction] = {
  71.     e match {
  72.       // dispatch compile calls for block-statements
  73.       case Block(es @ _*) => compile(es: _*)
  74.       // compile number constants
  75.       case Num(n) =>
  76.         Push(n)
  77.       // compile string constants
  78.       case Var(n) =>
  79.         Store(renameVariable(n))
  80.       // compile addition
  81.       case Add(l, n) =>
  82.         compile(l) ++ compile(n) ++ Plus()
  83.       // compile substraction
  84.       case Sub(l, n) =>
  85.         compile(l) ++ compile(n) ++ Minus()
  86.       // compile multiplication
  87.       case Mul(l, n) =>
  88.         compile(l) ++ compile(n) ++ Times()
  89.       // compile less than
  90.       case Lt(l, n) =>
  91.         compile(l) ++ compile(n) ++ LessThan()
  92.       // compile variable reference
  93.       case Assign(l, n) =>
  94.         compile(n) ++ Store(l)
  95.       // compile if-then-else
  96.       case IfThenElse(c, t, e) => {
  97.         val cj = uniqueName()
  98.         val el = uniqueName()
  99.         val f = uniqueName()
  100.         compile(c) ++ Push(0) ++ Equal() ++ CJump(el) ++ compile(t) ++ Jump(f) ++ Label(el) ++ compile(e) ++ Label(f)
  101.       }
  102.       // compile while statements
  103.       case While(c, body) => {
  104.         val w = uniqueName()
  105.         compile(c) ++ Push(0) ++ Equal() ++ CJump("elihw") ++ compile(body) ++ Jump("while") ++ Label("elihw")
  106.       }
  107.       // compile repeat
  108.       case Repeat(body, c) => {
  109.         Label("body") ++ compile(body) ++ compile(c) ++ Push(1) ++ Equal() ++ CJump("body")
  110.       }        
  111.        
  112.     }
  113.   }
  114. }
  115. //
Add Comment
Please, Sign In to add comment