Skip to content

Commit

Permalink
addressing review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
kushti committed Oct 7, 2024
1 parent 5c4ccf1 commit 1d47d5f
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 22 deletions.
19 changes: 10 additions & 9 deletions core/shared/src/main/scala/sigma/Colls.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,10 @@ trait Coll[@specialized A] {
*/
def apply(i: Int): A

/** The element at given index.
* Indices start at `0`; `xs.apply(0)` is the first element of collection `xs`.
* Note the indexing syntax `xs(i)` is a shorthand for `xs.apply(i)`.
/** The element at given index or None if there is no such element. Indices start at `0`.
*
* @param i the index
* @return the element at the given index
* @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i`
* @return the element at the given index, or None if there is no such element
*/
def get(i: Int): Option[A] = {
if (isDefinedAt(i)) {
Expand Down Expand Up @@ -92,12 +89,16 @@ trait Coll[@specialized A] {
* produces a collection ((x0, y0), ..., (xK, yK)) where K = min(N, M) */
def zip[@specialized B](ys: Coll[B]): Coll[(A, B)]

/** For this collection (x0, ..., xN) and other collection (y0, ..., yM)
* produces a collection ((x0, y0), ..., (xK, yK)) where K = min(N, M) */
/**
* @return true if first elements of this collection form given `ys` collection, false otherwise.
* E.g. [1,2,3] starts with [1,2]
*/
def startsWith(ys: Coll[A]): Boolean

/** For this collection (x0, ..., xN) and other collection (y0, ..., yM)
* produces a collection ((x0, y0), ..., (xK, yK)) where K = min(N, M) */
/**
* @return true if last elements of this collection form given `ys` collection, false otherwise.
* E.g. [1,2,3] ends with [2,3]
*/
def endsWith(ys: Coll[A]): Boolean

/** Tests whether a predicate holds for at least one element of this collection.
Expand Down
10 changes: 8 additions & 2 deletions core/shared/src/main/scala/sigma/data/CollsOverArrays.scala
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,15 @@ class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R

def zip[@specialized B](ys: Coll[B]): PairColl[(L,R), B] = builder.pairColl(this, ys)

def startsWith(ys: Coll[(L, R)]): Boolean = toArray.startsWith(ys.toArray)
def startsWith(ys: Coll[(L, R)]): Boolean = ys match {
case yp: PairOfCols[L, R] => ls.startsWith(yp.ls) && rs.startsWith(yp.rs)
case _ => toArray.startsWith(ys.toArray)
}

def endsWith(ys: Coll[(L, R)]): Boolean = toArray.endsWith(ys.toArray)
def endsWith(ys: Coll[(L, R)]): Boolean = ys match {
case yp: PairOfCols[L, R] => ls.endsWith(yp.ls) && rs.endsWith(yp.rs)
case _ => toArray.endsWith(ys.toArray)
}

override def indices: Coll[Int] = if (ls.length <= rs.length) ls.indices else rs.indices

Expand Down
26 changes: 26 additions & 0 deletions core/shared/src/test/scala/sigma/CollsTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,32 @@ class CollsTests extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers
}
}

property("Coll.startsWith") {
val minSuccess = minSuccessful(50)
forAll(collGen, minSuccess) { col =>
val n = col.length / 2
val prefix = col.take(n)
val pairs = col.zip(col)
pairs.startsWith(prefix.zip(prefix)) shouldBe true
col.startsWith(prefix) shouldBe true
val pairOfCols = new PairOfCols[Int, Int](col, col)
pairOfCols.startsWith(pairOfCols.take(n)) shouldBe true
}
}

property("Coll.endsWith") {
val minSuccess = minSuccessful(50)
forAll(collGen, minSuccess) { col =>
val n = col.length / 2
val suffix = col.slice(n, col.length)
col.endsWith(suffix) shouldBe true
val pairs = col.zip(col)
pairs.endsWith(suffix.zip(suffix)) shouldBe true
val pairOfCols = new PairOfCols[Int, Int](col, col)
pairOfCols.endsWith(pairOfCols.slice(n, col.length)) shouldBe true
}
}

property("Coll.equals") {
def checkColls(repl: Coll[_], coll: Coll[_]) = {
assert(coll == repl)
Expand Down
31 changes: 22 additions & 9 deletions data/shared/src/main/scala/sigma/ast/methods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1070,8 +1070,10 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply {

// ======== 6.0 methods below ===========

private val reverseCostKind = Append.costKind

val ReverseMethod = SMethod(this, "reverse",
SFunc(Array(ThisType), ThisType, paramIVSeq), 30, Zip_CostKind) // todo: costing
SFunc(Array(ThisType), ThisType, paramIVSeq), 30, reverseCostKind)
.withIRInfo(MethodCallIrBuilder)
.withInfo(MethodCall, "")

Expand All @@ -1087,10 +1089,12 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply {
}
}

private val distinctCostKind = PerItemCost(baseCost = JitCost(60), perChunkCost = JitCost(5), chunkSize = 100)

val DistinctMethod = SMethod(this, "distinct",
SFunc(Array(ThisType), ThisType, paramIVSeq), 31, Zip_CostKind) // todo: costing
SFunc(Array(ThisType), ThisType, paramIVSeq), 31, distinctCostKind)
.withIRInfo(MethodCallIrBuilder)
.withInfo(MethodCall, "")
.withInfo(MethodCall, "Returns inversed collection.")

/** Implements evaluation of Coll.reverse method call ErgoTree node.
* Called via reflection based on naming convention.
Expand All @@ -1104,10 +1108,13 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply {
}
}

private val startsWithCostKind = Zip_CostKind

val StartsWithMethod = SMethod(this, "startsWith",
SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 32, Zip_CostKind) // todo: costing
SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 32, startsWithCostKind)
.withIRInfo(MethodCallIrBuilder)
.withInfo(MethodCall, "")
.withInfo(MethodCall, "Returns true if this collection starts with given one, false otherwise.",
ArgInfo("prefix", "Collection to be checked for being a prefix of this collection."))

/** Implements evaluation of Coll.zip method call ErgoTree node.
* Called via reflection based on naming convention.
Expand All @@ -1121,10 +1128,13 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply {
}
}

private val endsWithCostKind = Zip_CostKind

val EndsWithMethod = SMethod(this, "endsWith",
SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 33, Zip_CostKind) // todo: costing
SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 33, endsWithCostKind)
.withIRInfo(MethodCallIrBuilder)
.withInfo(MethodCall, "")
.withInfo(MethodCall, "Returns true if this collection ends with given one, false otherwise.",
ArgInfo("suffix", "Collection to be checked for being a suffix of this collection."))

/** Implements evaluation of Coll.zip method call ErgoTree node.
* Called via reflection based on naming convention.
Expand All @@ -1139,9 +1149,12 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply {
}

val GetMethod = SMethod(this, "get",
SFunc(Array(ThisType, SInt), SOption(tIV), Array[STypeParam](tIV)), 34, ByIndex.costKind) //todo: costing
SFunc(Array(ThisType, SInt), SOption(tIV), Array[STypeParam](tIV)), 34, ByIndex.costKind)
.withIRInfo(MethodCallIrBuilder)
.withInfo(MethodCall, "")
.withInfo(MethodCall,
"Returns Some(element) if there is an element at given index, None otherwise.",
ArgInfo("index", "Index of an element (starting from 0).")
)

private val v5Methods = super.getMethods() ++ Seq(
SizeMethod,
Expand Down
8 changes: 6 additions & 2 deletions sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import sigma.ast.ErgoTree.ZeroHeader
import sigma.ast.SCollection.SByteArray
import sigma.ast.syntax.TrueSigmaProp
import sigma.ast.{SInt, _}
import sigma.data.{CBigInt, CBox, CHeader, CSigmaDslBuilder, ExactNumeric, RType}
import sigma.data.{CBigInt, CBox, CHeader, CSigmaDslBuilder, ExactNumeric, PairOfCols, RType}
import sigma.eval.{CostDetails, SigmaDsl, TracedCost}
import sigma.serialization.ValueCodes.OpCode
import sigma.util.Extensions.{BooleanOps, IntOps}
Expand Down Expand Up @@ -1639,6 +1639,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
Coll(1, 2) -> Expected(ExpectedResult(Success(Coll(1, 2)), None)),
Coll(1, 1, 2) -> Expected(ExpectedResult(Success(Coll(1, 2)), None)),
Coll(1, 2, 2) -> Expected(ExpectedResult(Success(Coll(1, 2)), None)),
Coll(2, 2, 2) -> Expected(ExpectedResult(Success(Coll(2)), None)),
Coll(3, 1, 2, 2, 2, 4, 4, 1) -> Expected(ExpectedResult(Success(Coll(3, 1, 2, 4)), None)),
Coll[Int]() -> Expected(ExpectedResult(Success(Coll[Int]()), None))
),
f
Expand All @@ -1656,8 +1658,10 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
Seq(
(Coll(1, 2, 3), Coll(1, 2)) -> Expected(ExpectedResult(Success(true), None)),
(Coll(1, 2, 3), Coll(1, 2, 3)) -> Expected(ExpectedResult(Success(true), None)),
(Coll(1, 2, 3), Coll(1, 2, 4)) -> Expected(ExpectedResult(Success(false), None)),
(Coll(1, 2, 3), Coll(1, 2, 3, 4)) -> Expected(ExpectedResult(Success(false), None)),
(Coll[Int](), Coll[Int]()) -> Expected(ExpectedResult(Success(true), None))
(Coll[Int](), Coll[Int]()) -> Expected(ExpectedResult(Success(true), None)),
(Coll[Int](1, 2), Coll[Int]()) -> Expected(ExpectedResult(Success(true), None))
),
f
)
Expand Down

0 comments on commit 1d47d5f

Please sign in to comment.