Skip to content
This repository was archived by the owner on May 7, 2024. It is now read-only.

implement Path and Slot #6

Merged
merged 9 commits into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ lazy val root = project

scalaVersion := scala3Version,

libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test
libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test,
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.15" % "test"
)
5 changes: 0 additions & 5 deletions src/main/scala/Main.scala

This file was deleted.

68 changes: 68 additions & 0 deletions src/main/scala/Path.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* A path is a list of slots that represent a path in a tree.
* The path works like a stack.
*/
trait Path:

/**
* Pushes a slot to the path
* @param slot the slot to push
* @return the new path
*/
def push(slot: Slot): Path

/**
* Pulls the last slot from the top of the path
* @return the new path
*/
def pull(): Path

/**
* Checks if the path is equal to another path
* @param path the path to check
* @return true if the paths are equal, false otherwise
*/
def isEqualTo(path: Path): Boolean

/**
* Checks if the path is the root path
* @return true if the path is the root path, false otherwise
*/
def isRoot: Boolean

/**
* Returns the head of the path (the last slot pushed)
* @return the head of the path
*/
def head: Slot

/**
* @return the path as a list of slots
*/
def path: List[Slot]

/**
* Pushes a slot to the path
* @param slot the slot to push
* @return the new path
*/
def /(slot: Slot): Path = push(slot)

object Path:
def apply(slots: Slot*): Path = PathImpl(slots.toList.reverse)

private case class PathImpl(path: List[Slot]) extends Path:

override def push(slot: Slot): Path = PathImpl(slot :: path)

override def pull(): Path = path match
case _ :: p => PathImpl(p)
case _ => throw new Exception()

override def isEqualTo(path: Path): Boolean = this == path

override def isRoot: Boolean = path.isEmpty

override def head: Slot = path.head

override def toString: String = "P:/" + path.reverse.mkString("/")
20 changes: 20 additions & 0 deletions src/main/scala/Slot.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
trait Slot:
/**
* This method is used to associate a value to a path.
* @param value the value to be associated with the path
* @return a tuple containing a path and the corresponding value
*/
def -> (value: Any): (Path, Any) = (Path(this), value)

/**
* Creates a path by concatenating this slot with the given slot.
* @param slot the slot to be concatenated
* @return a path
*/
def /(slot: Slot): Path = Path(this, slot)

object Slot:
final case class Nbr(index: Int) extends Slot
final case class Rep(index: Int) extends Slot
final case class FoldHood(index: Int) extends Slot
final case class Branch(index: Int, tag: Boolean) extends Slot
9 changes: 0 additions & 9 deletions src/test/scala/MySuite.scala

This file was deleted.

65 changes: 65 additions & 0 deletions src/test/scala/PathTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import Slot.{Branch, FoldHood, Nbr, Rep}
import org.scalatest.flatspec.AnyFlatSpec

class PathTest extends AnyFlatSpec:

behavior of "Path"

it should "be empty" in {
val path = Path()
assert(path.path.isEmpty)
}

it should "have size 3" in {
val path = Path(Rep(0), Nbr(1), Nbr(2))
assert(path.path.size == 3)
}

it should "correctly push a Slot" in {
val path = Path(Rep(0), Nbr(1))
val pathAfterPush = path.push(Nbr(2))
assert(pathAfterPush.path == List(Rep(0), Nbr(1), Nbr(2)).reverse)
}

it should "correctly pop a Slot" in {
val path = Path(Rep(0), Nbr(1), Nbr(2))
assert(path.pull().path == List(Rep(0), Nbr(1)).reverse)
}

it should "be equal to another Path" in {
val path1 = Path(Rep(0), Nbr(1), Nbr(2))
val path2 = Path(Rep(0), Nbr(1), Nbr(2))
assert(path1 isEqualTo path2)
}

it should "NOT be equal to another Path" in {
val path1 = Path(Rep(0), Nbr(1), Nbr(2))
val path2 = Path(Rep(0), Nbr(1), Nbr(3))
assert(!(path1 isEqualTo path2))
}

it should "be root" in {
val path = Path()
assert(path.isRoot)
}

it should "NOT be root" in {
val path = Path(Rep(0), Nbr(1), Nbr(2))
assert(!path.isRoot)
}

it should "return the head Slot" in {
val path = Path(Rep(0), Nbr(1), Nbr(2))
assert(path.head == Nbr(2))
}

it should "add a slot correctly using / method" in {
val path = Path(Rep(0))
val pathAfterAdd = path / FoldHood(1) / Branch(1, false)
assert(pathAfterAdd.path == List(Rep(0), FoldHood(1), Branch(1, false)).reverse)
}

it should "print correctly" in {
val path = Path(Rep(0), Nbr(1), Nbr(2))
assert(path.toString == "P:/Rep(0)/Nbr(1)/Nbr(2)")
}
15 changes: 15 additions & 0 deletions src/test/scala/SlotTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Slot.{Nbr, Rep}
import org.scalatest.flatspec.AnyFlatSpec

class SlotTest extends AnyFlatSpec:

behavior of "Slot"

it should "create a Path" in {
val path = Rep(0) / Nbr(1)
assert(path.path == List(Rep(0), Nbr(1)).reverse)
}

it should "associate a value to a path" in {
assert(Rep(0) -> "test" == (Path(Rep(0)), "test"))
}