Skip to content

Instantly share code, notes, and snippets.

@Alefas
Created February 3, 2015 14:48
Show Gist options
  • Save Alefas/544346c7e809d5ac070c to your computer and use it in GitHub Desktop.
Save Alefas/544346c7e809d5ac070c to your computer and use it in GitHub Desktop.
package abstr.interpretation
import scala.annotation.tailrec
import scala.util.parsing.combinator.RegexParsers
/**
* @author Alefas
* @since 03/02/15.
*/
object ThreeCounterInterpreter {
sealed trait Operation
case class Inc(v: Var) extends Operation
case class Dec(v: Var) extends Operation
case class Zero(test: Var, th: Int, el: Int) extends Operation
case object Stop extends Operation
sealed trait Var
case object X extends Var
case object Y extends Var
case object Z extends Var
object LineParser extends RegexParsers {
val VAR: Parser[Var] = "x" ^^ {_ => X} | "y" ^^ {_ => Y} | "z" ^^ {_ => Z}
val inc: Parser[Operation] = "inc" ~> VAR ^^ Inc
val dec: Parser[Operation] = "dec" ~> VAR ^^ Dec
val line: Parser[Int] = """\d+""".r ^^ {_.toInt}
val zero: Parser[Operation] = "zero" ~> VAR ~ line ~ ("else" ~> line) ^^ {
case v ~ th ~ e => Zero(v, th, e)
}
val stop: Parser[Operation] = "stop" ^^ {_ => Stop}
val expression: Parser[Operation] = inc | dec | zero | stop
def parse(s: String): Operation = {
try {
LineParser.parse(LineParser.expression, s).get
}
catch {
case _: Throwable =>
println(s"error for $s")
Stop
}
}
}
def main(args: Array[String]) {
val program =
"""
|zero x 7 else 2
|inc y
|inc y
|inc y
|dec x
|zero x 1 else 1
|stop
""".stripMargin
val operationList = program.lines.filter(_.nonEmpty).map(LineParser.parse).toSeq
case class State(position: Int, x: Int, y: Int, z: Int)
@tailrec
def iterateProgram(state: State): State = {
println(state)
operationList(state.position - 1) match {
case Inc(X) => iterateProgram(State(state.position + 1, state.x + 1, state.y, state.z))
case Inc(Y) => iterateProgram(State(state.position + 1, state.x, state.y + 1, state.z))
case Inc(Z) => iterateProgram(State(state.position + 1, state.x, state.y, state.z + 1))
case Dec(X) if state.x > 0 => iterateProgram(State(state.position + 1, state.x - 1, state.y, state.z))
case Dec(Y) if state.y > 0 => iterateProgram(State(state.position + 1, state.x, state.y - 1, state.z))
case Dec(Z) if state.z > 0 => iterateProgram(State(state.position + 1, state.x, state.y, state.z - 1))
case Zero(X, i, j) if state.x == 0 => iterateProgram(State(i, state.x, state.y, state.z))
case Zero(X, i, j) if state.x != 0 => iterateProgram(State(j, state.x, state.y, state.z))
case Zero(Y, i, j) if state.y == 0 => iterateProgram(State(i, state.x, state.y, state.z))
case Zero(Y, i, j) if state.y != 0 => iterateProgram(State(j, state.x, state.y, state.z))
case Zero(Z, i, j) if state.z == 0 => iterateProgram(State(i, state.x, state.y, state.z))
case Zero(Z, i, j) if state.z != 0 => iterateProgram(State(j, state.x, state.y, state.z))
case _ => state
}
}
val initialValue = 5
val result = iterateProgram(State(1, initialValue, 0, 0))
println(result.y)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment