diff --git a/build.sbt b/build.sbt index 060ed5f..c354fde 100644 --- a/build.sbt +++ b/build.sbt @@ -52,6 +52,7 @@ lazy val root = (project in file(".")). // Dependencies libraryDependencies ++= Seq( scalaParserCombinators, + cats, scalaTest % Test, scalaCheck % Test ), diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 0dd0694..bebd634 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -4,4 +4,5 @@ object Dependencies { lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.1" lazy val scalaCheck = "org.scalacheck" %% "scalacheck" % "1.13.4" lazy val scalaParserCombinators = "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.5" + lazy val cats = "org.typelevel" %% "cats" % "0.9.0" } diff --git a/src/main/scala/edu/colorado/plv/cuanto/jsy/imp/Parser.scala b/src/main/scala/edu/colorado/plv/cuanto/jsy/imp/Parser.scala new file mode 100644 index 0000000..282ce5a --- /dev/null +++ b/src/main/scala/edu/colorado/plv/cuanto/jsy/imp/Parser.scala @@ -0,0 +1,6 @@ +package edu.colorado.plv.cuanto.jsy.imp + +import edu.colorado.plv.cuanto.jsy.common.UnitOpParser +import edu.colorado.plv.cuanto.jsy.{mutation, numerical} + +object Parser extends UnitOpParser with mutation.ParserLike with numerical.ParserWithBindingLike diff --git a/src/main/scala/edu/colorado/plv/cuanto/jsy/imp/package.scala b/src/main/scala/edu/colorado/plv/cuanto/jsy/imp/package.scala new file mode 100644 index 0000000..738aa08 --- /dev/null +++ b/src/main/scala/edu/colorado/plv/cuanto/jsy/imp/package.scala @@ -0,0 +1,21 @@ +package edu.colorado.plv.cuanto.jsy + +import edu.colorado.plv.cuanto.jsy.binding.Mode + +package imp { + + /** Mode `var`. Mutable variables. + * + * @group Abstract Syntax Nodes + */ + case object MVar extends Mode + +} + +/** The Imp subset of JavaScripty. + * + * Mixes [[numerical]] and [[mutation]]. + * + * @author Bor-Yuh Evan Chang + */ +package object imp diff --git a/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/Parser.scala b/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/Parser.scala index 0b18921..8cb1999 100644 --- a/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/Parser.scala +++ b/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/Parser.scala @@ -1,14 +1,15 @@ -package edu.colorado.plv.cuanto.jsy.mutation +package edu.colorado.plv.cuanto.jsy +package mutation -import edu.colorado.plv.cuanto.jsy.common.{JsyParserLike, OpParserLike, UnitOpParser} +import edu.colorado.plv.cuanto.jsy.common.{JsyParserLike, OpParserLike} -trait ParserLike extends OpParserLike with JsyParserLike +trait ParserLike extends OpParserLike with JsyParserLike { + abstract override def opAtom: Parser[Expr] = + positioned("null" ^^^ Null) | + super.opAtom -/** - * @author Bor-Yuh Evan Chang - */ -object Parser extends UnitOpParser with ParserLike { - override val bop = ??? - override def expr = ??? - override def start = ??? + lazy val mutationBop: OpPrecedence = List( + List("=" -> Assign) + ) } + diff --git a/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/mem/Mem.scala b/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/mem/Mem.scala new file mode 100644 index 0000000..2162539 --- /dev/null +++ b/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/mem/Mem.scala @@ -0,0 +1,41 @@ +package edu.colorado.plv.cuanto.jsy +package mutation.mem + +import cats.data.State + +/** Address. + * + * @group Intermediate AST Nodes + */ +case class A private (a: Int) extends Val + +/** Memory. + * + * Memory is a mapping from addresses to values. It enforces the invariant that + * addresses are allocated in this module. + * + * @tparam V The value type stored in this memory + * @author Bor-Yuh Evan Chang + */ +class Mem[V] private (map: Map[A, V], nextAddr: Int) { + def apply(key: A): V = map(key) + def get(key: A): Option[V] = map.get(key) + def +(kv: (A, V)): Mem[V] = new Mem[V](map + kv, nextAddr) + def contains(key: A): Boolean = map.contains(key) + override def toString: String = map.toString + + private def alloc(v: V): (Mem[V], A) = { + val fresha = A(nextAddr) + (new Mem[V](map + (fresha -> v), nextAddr + 1), fresha) + } +} + +object Mem { + def empty[V]: Mem[V] = new Mem[V](Map.empty, 1) + + /** Get a fresh address. */ + def alloc[V](v: V): State[Mem[V], A] = State.get flatMap { m => + val (mp, a) = m.alloc(v) + State.set(mp) map { _ => a } + } +} diff --git a/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/package.scala b/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/package.scala index 1e9cd0d..7b8957b 100644 --- a/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/package.scala +++ b/src/main/scala/edu/colorado/plv/cuanto/jsy/mutation/package.scala @@ -11,12 +11,6 @@ package mutation { /** @group Intermediate AST Nodes */ case object Deref extends Uop - /** Address. - * - * @group Intermediate AST Nodes - */ - case class A private (a: Int) extends Val - } diff --git a/src/main/scala/edu/colorado/plv/cuanto/jsy/string/package.scala b/src/main/scala/edu/colorado/plv/cuanto/jsy/string/package.scala index 19b9d17..22dcd7c 100644 --- a/src/main/scala/edu/colorado/plv/cuanto/jsy/string/package.scala +++ b/src/main/scala/edu/colorado/plv/cuanto/jsy/string/package.scala @@ -17,6 +17,6 @@ package object string { /** The string concatenation operator is syntactically overloaded as * [[edu.colorado.plv.cuanto.jsy.arithmetic.Plus]]. */ - val Concat: Bop = arithmetic.Plus + val Concat = arithmetic.Plus } diff --git a/src/test/scala/edu/colorado/plv/cuanto/jsy/imp/ImpParserSpec.scala b/src/test/scala/edu/colorado/plv/cuanto/jsy/imp/ImpParserSpec.scala new file mode 100644 index 0000000..a2bd3cd --- /dev/null +++ b/src/test/scala/edu/colorado/plv/cuanto/jsy/imp/ImpParserSpec.scala @@ -0,0 +1,35 @@ +package edu.colorado.plv.cuanto.jsy +package imp + +import edu.colorado.plv.cuanto.CuantoSpec +import edu.colorado.plv.cuanto.jsy.arithmetic.N +import edu.colorado.plv.cuanto.jsy.binding._ +import edu.colorado.plv.cuanto.jsy.boolean._ +import edu.colorado.plv.cuanto.jsy.common.ParserBehaviors +import edu.colorado.plv.cuanto.jsy.mutation.Assign + +/** + * @author Bor-Yuh Evan Chang + */ +class ImpParserSpec extends CuantoSpec with ParserBehaviors { + + override lazy val positives = Table( + "concrete" -> "abstract", + """{ let x = 3 + | var y = true + | if (y) { x = 4 } else { x = 5 } + |} + """.stripMargin + -> Bind(MVar, Var("x"), N(3), + Bind(MVar, Var("y"), B(true), + If(Var("y"), + Binary(Assign, Var("x"), N(4)), + Binary(Assign, Var("x"), N(4)) + ) + ) + ) + + ) + + "jsy.imp.Parser" should behave like parser(Parser.parse) +} \ No newline at end of file diff --git a/src/test/scala/edu/colorado/plv/cuanto/jsy/mutation/MutationParserSpec.scala b/src/test/scala/edu/colorado/plv/cuanto/jsy/mutation/MutationParserSpec.scala deleted file mode 100644 index 133ffc6..0000000 --- a/src/test/scala/edu/colorado/plv/cuanto/jsy/mutation/MutationParserSpec.scala +++ /dev/null @@ -1,16 +0,0 @@ -package edu.colorado.plv.cuanto.jsy.mutation - -import edu.colorado.plv.cuanto.CuantoSpec -import edu.colorado.plv.cuanto.jsy.common.ParserBehaviors - -/** - * @author Bor-Yuh Evan Chang - */ -class MutationParserSpec extends CuantoSpec with ParserBehaviors { - - override lazy val positives = Table( - "concrete" -> "abstract" - ) - - "jsy.objects.Parser" should behave like parser(Parser.parse) -} \ No newline at end of file