-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[6.0] New collection methods #1010
Changes from 12 commits
7ccce9a
2fa224b
b17c8c8
fc3be57
acb76c9
877ed78
9fd499a
8136c8f
d738ac5
1989d19
6459b07
5c4ccf1
1d47d5f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,22 @@ 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)`. | ||
* | ||
* @param i the index | ||
* @return the element at the given index | ||
* @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i` | ||
*/ | ||
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 | ||
|
@@ -76,6 +92,14 @@ 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) */ | ||
def startsWith(ys: Coll[A]): Boolean | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ScalaDoc is not correct. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
|
||
/** For this collection (x0, ..., xN) and other collection (y0, ..., yM) | ||
* produces a collection ((x0, y0), ..., (xK, yK)) where K = min(N, M) */ | ||
def endsWith(ys: Coll[A]): Boolean | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ScalaDoc is not correct. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
|
||
/** 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` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) { | ||
|
@@ -350,6 +354,10 @@ 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 endsWith(ys: Coll[(L, R)]): Boolean = toArray.endsWith(ys.toArray) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is simple, but inefficient ((ys.length + 1)*2 allocations) fallback implementation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done, added tests also |
||
|
||
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] = | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1020,7 +1020,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { | |
SFunc(Array(ThisType, tIV, SInt), SInt, paramIVSeq), | ||
26, PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(10), chunkSize = 2)) | ||
.withIRInfo(MethodCallIrBuilder, javaMethodOf[Coll[_], Any, Int]("indexOf")) | ||
.withInfo(MethodCall, "") | ||
.withInfo(MethodCall, "Returns index of a collection element, or -1 if not found") | ||
|
||
/** Implements evaluation of Coll.indexOf method call ErgoTree node. | ||
* Called via reflection based on naming convention. | ||
|
@@ -1052,8 +1052,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { | |
baseCost = JitCost(10), perChunkCost = JitCost(1), chunkSize = 10) | ||
|
||
val ZipMethod = SMethod(this, "zip", | ||
SFunc(Array(ThisType, tOVColl), SCollection(STuple(tIV, tOV)), Array[STypeParam](tIV, tOV)), | ||
29, Zip_CostKind) | ||
SFunc(Array(ThisType, tOVColl), SCollection(STuple(tIV, tOV)), Array[STypeParam](tIV, tOV)), 29, Zip_CostKind) | ||
.withIRInfo(MethodCallIrBuilder) | ||
.withInfo(MethodCall, "") | ||
|
||
|
@@ -1069,29 +1068,120 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { | |
} | ||
} | ||
|
||
// ======== 6.0 methods below =========== | ||
|
||
val ReverseMethod = SMethod(this, "reverse", | ||
SFunc(Array(ThisType), ThisType, paramIVSeq), 30, Zip_CostKind) // todo: costing | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest to declare the descriptor by just cloning from Append (Zip is too small). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
.withIRInfo(MethodCallIrBuilder) | ||
.withInfo(MethodCall, "") | ||
|
||
/** Implements evaluation of Coll.reverse method call ErgoTree node. | ||
* Called via reflection based on naming convention. | ||
* @see SMethod.evalMethod | ||
*/ | ||
def reverse_eval[A](mc: MethodCall, xs: Coll[A]) | ||
(implicit E: ErgoTreeEvaluator): Coll[A] = { | ||
val m = mc.method | ||
E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () => | ||
xs.reverse | ||
} | ||
} | ||
|
||
val DistinctMethod = SMethod(this, "distinct", | ||
SFunc(Array(ThisType), ThisType, paramIVSeq), 31, Zip_CostKind) // todo: costing | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The cost of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
.withIRInfo(MethodCallIrBuilder) | ||
.withInfo(MethodCall, "") | ||
|
||
/** Implements evaluation of Coll.reverse method call ErgoTree node. | ||
* Called via reflection based on naming convention. | ||
* @see SMethod.evalMethod | ||
*/ | ||
def distinct_eval[A](mc: MethodCall, xs: Coll[A]) | ||
(implicit E: ErgoTreeEvaluator): Coll[A] = { | ||
val m = mc.method | ||
E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () => | ||
xs.distinct | ||
} | ||
} | ||
|
||
val StartsWithMethod = SMethod(this, "startsWith", | ||
SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 32, Zip_CostKind) // todo: costing | ||
.withIRInfo(MethodCallIrBuilder) | ||
.withInfo(MethodCall, "") | ||
|
||
/** Implements evaluation of Coll.zip method call ErgoTree node. | ||
* Called via reflection based on naming convention. | ||
* @see SMethod.evalMethod | ||
*/ | ||
def startsWith_eval[A](mc: MethodCall, xs: Coll[A], ys: Coll[A]) | ||
(implicit E: ErgoTreeEvaluator): Boolean = { | ||
val m = mc.method | ||
E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () => | ||
xs.startsWith(ys) | ||
} | ||
} | ||
|
||
val EndsWithMethod = SMethod(this, "endsWith", | ||
SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 33, Zip_CostKind) // todo: costing | ||
.withIRInfo(MethodCallIrBuilder) | ||
.withInfo(MethodCall, "") | ||
|
||
/** Implements evaluation of Coll.zip method call ErgoTree node. | ||
* Called via reflection based on naming convention. | ||
* @see SMethod.evalMethod | ||
*/ | ||
def endsWith_eval[A](mc: MethodCall, xs: Coll[A], ys: Coll[A]) | ||
(implicit E: ErgoTreeEvaluator): Boolean = { | ||
val m = mc.method | ||
E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () => | ||
xs.endsWith(ys) | ||
} | ||
} | ||
|
||
val GetMethod = SMethod(this, "get", | ||
SFunc(Array(ThisType, SInt), SOption(tIV), Array[STypeParam](tIV)), 34, ByIndex.costKind) //todo: costing | ||
.withIRInfo(MethodCallIrBuilder) | ||
.withInfo(MethodCall, "") | ||
|
||
private val v5Methods = super.getMethods() ++ Seq( | ||
SizeMethod, | ||
GetOrElseMethod, | ||
MapMethod, | ||
ExistsMethod, | ||
FoldMethod, | ||
ForallMethod, | ||
SliceMethod, | ||
FilterMethod, | ||
AppendMethod, | ||
ApplyMethod, | ||
IndicesMethod, | ||
FlatMapMethod, | ||
PatchMethod, | ||
UpdatedMethod, | ||
UpdateManyMethod, | ||
IndexOfMethod, | ||
ZipMethod | ||
) | ||
|
||
private val v6Methods = v5Methods ++ Seq( | ||
ReverseMethod, | ||
DistinctMethod, | ||
StartsWithMethod, | ||
EndsWithMethod, | ||
GetMethod | ||
) | ||
|
||
/** This method should be overriden in derived classes to add new methods in addition to inherited. | ||
* Typical override: `super.getMethods() ++ Seq(m1, m2, m3)` | ||
*/ | ||
override protected def getMethods(): Seq[SMethod] = super.getMethods() ++ | ||
Seq( | ||
SizeMethod, | ||
GetOrElseMethod, | ||
MapMethod, | ||
ExistsMethod, | ||
FoldMethod, | ||
ForallMethod, | ||
SliceMethod, | ||
FilterMethod, | ||
AppendMethod, | ||
ApplyMethod, | ||
IndicesMethod, | ||
FlatMapMethod, | ||
PatchMethod, | ||
UpdatedMethod, | ||
UpdateManyMethod, | ||
IndexOfMethod, | ||
ZipMethod | ||
) | ||
override protected def getMethods(): Seq[SMethod] = { | ||
if (VersionContext.current.isV6SoftForkActivated) { | ||
v6Methods | ||
} else { | ||
v5Methods | ||
} | ||
} | ||
|
||
} | ||
|
||
object STupleMethods extends MethodsContainer { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ScalaDoc doesn't correspond to the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed