Skip to content

Commit

Permalink
[base] Add an id variant of the string concatenator repeated
Browse files Browse the repository at this point in the history
Also, add some unit tests for the new repeateds
  • Loading branch information
rayrobdod committed Feb 24, 2024
1 parent ab1c03c commit c8b9995
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
22 changes: 22 additions & 0 deletions Base/src/main/scala/typeclass/Repeat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ trait BiRepeated[Expr[_], A, Z]

/** Predefined implicit implementations of Repeated */
object Repeated extends VersionSpecificRepeated with LowPrioRepeated {
private def apply[A, Acc, Z](
initFn: () => Acc,
appendFn: (Acc, A) => Acc,
resultFn: Acc => Z,
): Repeated[A, Z] = {
type Acc2 = Acc
new Repeated[A, Z] {
type Acc = Acc2
def init():Acc = initFn()
def append(acc:Acc, elem:A):Acc = appendFn(acc, elem)
def result(acc:Acc):Z = resultFn(acc)
}
}

/**
* Repeated units results in a unit
*/
Expand Down Expand Up @@ -124,6 +138,14 @@ object Repeated extends VersionSpecificRepeated with LowPrioRepeated {
}
new RepeatedCodepoint()
}

def idConcatenateString:Repeated[String, String] = {
Repeated.apply(
() => new StringBuilder,
(acc:StringBuilder, elem:String) => acc ++= elem,
(acc:StringBuilder) => acc.toString,
)
}
}

private[typeclass] trait LowPrioRepeated {
Expand Down
28 changes: 28 additions & 0 deletions Base/src/test/scala-3/typeclass/VersonSpecificRepeatedTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package name.rayrobdod.stringContextParserCombinator
package typeclass
package repeated

import scala.quoted.*
import munit.Location

final class QuotedConcatenateStringTest extends munit.FunSuite {
inline def assertParseSuccess(
inline sc: StringContext,
inline args: Any*)(
expecting:String)(
using loc:Location
):Unit = ${
QuotedConcatenateStringTestImpls.assertParseSuccessImpl(
'this, 'sc, 'args, 'expecting, 'loc)
}

test ("0") {
assertParseSuccess(StringContext(""))("")
}
test ("1") {
assertParseSuccess(StringContext("ab"))("ab")
}
test ("many") {
assertParseSuccess(StringContext("ab", "cd", "ef"), "12", "34")("ab12cd34ef")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package name.rayrobdod.stringContextParserCombinator
package typeclass
package repeated

import scala.quoted.*
import munit.Location
import Interpolator.{charWhere, ofType, end}

object QuotedConcatenateStringTestImpls {
def assertParseSuccessImpl(
self: Expr[munit.FunSuite],
sc: Expr[StringContext],
args: Expr[Seq[Any]],
expecting: Expr[String],
loc: Expr[Location])(
using Quotes
):Expr[Unit] = {

val dut = (charWhere(_ => true).repeat(1).mapToExpr orElse ofType[String])
.repeat()(using Repeated.quotedConcatenateString)
.andThen(end)

val actual = dut.interpolate(sc, args)

'{
given Location = ${loc}
$self.assertEquals($actual, $expecting)
}
}
}
21 changes: 21 additions & 0 deletions Base/src/test/scala/typeclass/RepeatedTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package name.rayrobdod.stringContextParserCombinator
package typeclass
package repeated

import Interpolator.idInterpolators.{charWhere, ofType, end}

final class IdConcatenateString extends BaseInterpolatorSuite {
val dut = (charWhere(_ => true).repeat(1) orElse ofType[String])
.repeat()(using Repeated.idConcatenateString)
.andThen(end)

test ("0") {
assertParseSuccess(dut, ("" :: Nil, Nil), "")
}
test ("1") {
assertParseSuccess(dut, ("ab" :: Nil, Nil), "ab")
}
test ("many") {
assertParseSuccess(dut, ("ab" :: "cd" :: "ef" :: Nil, "12" :: "34" :: Nil), "ab12cd34ef")
}
}

0 comments on commit c8b9995

Please sign in to comment.