Skip to content

Commit

Permalink
merging w. 6.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
kushti committed Oct 8, 2024
2 parents 8f45909 + 83ba4a4 commit f151e1d
Show file tree
Hide file tree
Showing 19 changed files with 881 additions and 31 deletions.
25 changes: 25 additions & 0 deletions core/shared/src/main/scala/sigma/Colls.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ trait Coll[@specialized A] {
*/
def apply(i: Int): A

/** 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, or None if there is no such element
*/
def get(i: Int): Option[A] = {
if (isDefinedAt(i)) {
Some(apply(i))
} else {
None
}
}

/** Tests whether this $coll contains given index.
*
* The implementations of methods `apply` and `isDefinedAt` turn a `Coll[A]` into
Expand Down Expand Up @@ -76,6 +89,18 @@ 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)]

/**
* @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

/**
* @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.
* @param p the predicate used to test elements.
* @return `true` if the given predicate `p` is satisfied by at least one element of this collection, otherwise `false`
Expand Down
6 changes: 5 additions & 1 deletion core/shared/src/main/scala/sigma/SigmaDsl.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package sigma

import java.math.BigInteger
import sigma.ast.SType

import java.math.BigInteger
import sigma.data._

/**
Expand Down Expand Up @@ -763,5 +764,8 @@ trait SigmaDslBuilder {

/** Returns a byte-wise XOR of the two collections of bytes. */
def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte]

/** Returns a number decoded from provided big-endian bytes array. */
def fromBigEndianBytes[T](bytes: Coll[Byte])(implicit cT: RType[T]): T
}

14 changes: 14 additions & 0 deletions core/shared/src/main/scala/sigma/data/CollsOverArrays.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ class CollOverArray[@specialized A](val toArray: Array[A], val builder: CollBuil

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

@inline def startsWith(ys: Coll[A]): Boolean = toArray.startsWith(ys.toArray)

@inline def endsWith(ys: Coll[A]): Boolean = toArray.endsWith(ys.toArray)

def append(other: Coll[A]): Coll[A] = {
if (toArray.length <= 0) return other
val result = if (VersionContext.current.isJitActivated) {
Expand Down Expand Up @@ -350,6 +354,16 @@ 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 = 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 = 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

override def flatMap[B: RType](f: ((L, R)) => Coll[B]): Coll[B] =
Expand Down
18 changes: 18 additions & 0 deletions core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ object ReflectionData {
mkMethod(clazz, "apply", Array[Class[_]](classOf[Int])) { (obj, args) =>
obj.asInstanceOf[Coll[_]].apply(args(0).asInstanceOf[Int])
},
mkMethod(clazz, "get", Array[Class[_]](classOf[Int])) { (obj, args) =>
obj.asInstanceOf[Coll[_]].get(args(0).asInstanceOf[Int])
},
mkMethod(clazz, "append", Array[Class[_]](classOf[Coll[_]])) { (obj, args) =>
obj.asInstanceOf[Coll[Any]].append(args(0).asInstanceOf[Coll[Any]])
},
Expand All @@ -170,6 +173,18 @@ object ReflectionData {
},
mkMethod(clazz, "map", Array[Class[_]](classOf[Function1[_, _]], classOf[RType[_]])) { (obj, args) =>
obj.asInstanceOf[Coll[Any]].map(args(0).asInstanceOf[Any => Any])(args(1).asInstanceOf[RType[Any]])
},
mkMethod(clazz, "reverse", Array[Class[_]]()) { (obj, args) =>
obj.asInstanceOf[Coll[Any]].reverse
},
mkMethod(clazz, "distinct", Array[Class[_]]()) { (obj, args) =>
obj.asInstanceOf[Coll[Any]].distinct
},
mkMethod(clazz, "startsWith", Array[Class[_]](classOf[Coll[_]])) { (obj, args) =>
obj.asInstanceOf[Coll[Any]].startsWith(args(0).asInstanceOf[Coll[Any]])
},
mkMethod(clazz, "endsWith", Array[Class[_]](classOf[Coll[_]])) { (obj, args) =>
obj.asInstanceOf[Coll[Any]].endsWith(args(0).asInstanceOf[Coll[Any]])
}
)
)
Expand Down Expand Up @@ -450,6 +465,9 @@ object ReflectionData {
},
mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) =>
obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]])
},
mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](cColl, classOf[RType[_]])) { (obj, args) =>
obj.asInstanceOf[SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[Coll[Byte]])(args(1).asInstanceOf[RType[_]])
}
)
)
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
16 changes: 16 additions & 0 deletions data/shared/src/main/scala/sigma/SigmaDataReflection.scala
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,22 @@ object SigmaDataReflection {
mkMethod(clazz, "flatMap_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Function1[_,_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
obj.asInstanceOf[SCollectionMethods.type].flatMap_eval(args(0).asInstanceOf[MethodCall],
args(1).asInstanceOf[Coll[Any]], args(2).asInstanceOf[Any => Coll[Any]])(args(3).asInstanceOf[ErgoTreeEvaluator])
},
mkMethod(clazz, "reverse_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
obj.asInstanceOf[SCollectionMethods.type].reverse_eval(args(0).asInstanceOf[MethodCall],
args(1).asInstanceOf[Coll[Any]])(args(2).asInstanceOf[ErgoTreeEvaluator])
},
mkMethod(clazz, "distinct_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
obj.asInstanceOf[SCollectionMethods.type].distinct_eval(args(0).asInstanceOf[MethodCall],
args(1).asInstanceOf[Coll[Any]])(args(2).asInstanceOf[ErgoTreeEvaluator])
},
mkMethod(clazz, "startsWith_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
obj.asInstanceOf[SCollectionMethods.type].startsWith_eval(args(0).asInstanceOf[MethodCall],
args(1).asInstanceOf[Coll[Any]], args(2).asInstanceOf[Coll[Any]])(args(3).asInstanceOf[ErgoTreeEvaluator])
},
mkMethod(clazz, "endsWith_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
obj.asInstanceOf[SCollectionMethods.type].endsWith_eval(args(0).asInstanceOf[MethodCall],
args(1).asInstanceOf[Coll[Any]], args(2).asInstanceOf[Coll[Any]])(args(3).asInstanceOf[ErgoTreeEvaluator])
}
)
)
Expand Down
22 changes: 21 additions & 1 deletion data/shared/src/main/scala/sigma/ast/SigmaPredef.scala
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,25 @@ object SigmaPredef {
)
)

val FromBigEndianBytesFunc = PredefinedFunc("fromBigEndianBytes",
Lambda(Seq(paramT), Array("bytes" -> SByteArray), tT, None),
irInfo = PredefFuncInfo(
irBuilder = { case (u, args) =>
val resType = u.opType.tRange.asInstanceOf[SFunc].tRange
MethodCall(
Global,
SGlobalMethods.fromBigEndianBytesMethod.withConcreteTypes(Map(tT -> resType)),
args.toIndexedSeq,
Map(tT -> resType)
)
}),
docInfo = OperationInfo(MethodCall,
"""Deserializes provided big endian bytes into a numeric value of given type.
""".stripMargin,
Seq(ArgInfo("bytes", "bytes to deserialize"))
)
)

val globalFuncs: Map[String, PredefinedFunc] = Seq(
AllOfFunc,
AnyOfFunc,
Expand Down Expand Up @@ -448,7 +467,8 @@ object SigmaPredef {
SubstConstantsFunc,
ExecuteFromVarFunc,
ExecuteFromSelfRegFunc,
SerializeFunc
SerializeFunc,
FromBigEndianBytesFunc
).map(f => f.name -> f).toMap

def comparisonOp(symbolName: String, opDesc: ValueCompanion, desc: String, args: Seq[ArgInfo]) = {
Expand Down
Loading

0 comments on commit f151e1d

Please sign in to comment.