Skip to content

Instantly share code, notes, and snippets.

@joshcough
Created October 15, 2015 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshcough/da3c9917f8bdf69b3bdf to your computer and use it in GitHub Desktop.
Save joshcough/da3c9917f8bdf69b3bdf to your computer and use it in GitHub Desktop.
object L3Z {
import scalaz.Writer
import scalaz.std.list._
import scalaz.syntax.writer._
import scalaz.syntax.applicative._
import scalaz.syntax.foldable._
trait Exp
case class Num (i:Int) extends Exp
case class Add (l:Exp, r:Exp) extends Exp
case class Mult (l:Exp, r:Exp) extends Exp
case class Var (v: String) extends Exp
case class Let (v: (String, Exp), body:Exp) extends Exp
case class Print(e: Exp) extends Exp
case class Statements(es:List[Exp]) extends Exp
type Env = Map[String, Int]
type Output = List[String]
implicit class Parser(val sc: StringContext) extends AnyVal {
def v(args: Any*): Var = Var(sc.parts.mkString)
def n(args: Any*): Num = Num(sc.parts.mkString.toInt)
}
type W[A] = Writer[Output, A]
def die[A](msg: String, env: Env, out: Output): A =
sys.error(s"error: $msg, env: $env, output: ${out.mkString("\n")}")
def lookup(v: String, env: Env, output: Output): W[Int] =
env.getOrElse(v, die(s"unbound variable: $v", env, output)).pure[W]
def interp(node: Exp, env: Env=Map()): W[Int] =
node match {
case Num (i) => i.pure[W]
case Add (l,r) => for {
lv <- interp(l,env)
rv <- interp(l,env)
} yield lv+rv
case Mult(l,r) => for {
lv <- interp(l,env)
rv <- interp(l,env)
} yield lv*rv
case Var (x) =>
sys.error("todo")
//(lookup(x, env, output),output)
case Let ((x,e),b) => for {
ev <- interp(e, env)
bv <- interp(b, env + (x -> ev))
} yield bv
case Print(e) => for {
ev <- interp(e, env)
_ <- 0.set(List(ev.toString))
} yield 0
case Statements(es) => es.foldlM(0)(_ => e => interp(e, env))
}
def run(node: Exp, expected: Int) = {
val (out,i) = interp(node).run
if(i!=expected) sys.error(s"expected: $expected, but got: $i")
}
def main(args:Array[String]): Unit = {
run(n"7", 7)
run(Add (n"5", n"6"), 11)
run(Mult(n"5", n"6"), 30)
run(Let(("x", n"5"), v"x"), 5)
run(Let(("x", n"9"), Mult(v"x", v"x")), 81)
println("success!!")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment