Skip to content

Commit

Permalink
fix union types for ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
kasiaMarek committed Jan 6, 2024
1 parent ae72202 commit 6d83b54
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 30 deletions.
4 changes: 3 additions & 1 deletion src/main/scala/net/marek/tyre/pattern/Re.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ private case object ReEpsilon extends Re:
private case class ReHole(index: Int) extends Re:
override def toString(): String = s"@$index"

private case class ReLiteralConv(re: ReIn) extends Re:
override def toString(): String = s"$re!l"

private object Re:
def char(c: Char & Singleton): ReSingle = ReSingle(c)

private enum CastOp(val symbol: Char):
case Stringify extends CastOp('s')
case Literal extends CastOp('l')
21 changes: 7 additions & 14 deletions src/main/scala/net/marek/tyre/pattern/StringInterpolator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,26 +75,20 @@ private def tyreImpl(sc: Expr[StringContext], args: Expr[Seq[Any]])(using Quotes
case ReOpt(re) =>
toTyre(re) match
case '{ $ree: Tyre[t1] } => '{ Opt(${ ree }) }
case ReCast(ReIn(cs), CastOp.Literal) =>
case ReLiteralConv(ReIn(cs)) =>
assert(cs.map(_.size).sum <= 16)
val allChars = cs.flatMap(_.getChars)

def makeSingle(c : Char): Expr[Tyre[?]] = '{ Pred.single( ${ Expr(c) } ) }

def loop(acc: Expr[Tyre[?]], cs: List[Char]): Expr[Tyre[?]] =
def loop(cs: List[Char]): Expr[Tyre[?]] =
cs match
case Nil => acc
case Nil => '{ Pred.empty }
case c :: Nil => '{ Pred.single(${ Expr(c) }) }
case c :: tail =>
loop(acc, tail) match
loop(tail) match
case '{ $acce: Tyre[t] } =>
makeSingle(c) match
case '{ $s } => '{ OrM($s , ${ acce }) }
'{ OrMWithSingle(${ Expr(c) }, ${ acce }) }

allChars match
case Nil => '{ Pred.empty }
case c :: Nil => '{ Pred.single( ${ Expr(c) } ) }
case c :: c1 :: Nil => '{ OrM(Pred.single( ${ Expr(c) } ), Pred.single( ${ Expr(c1) } )) }
case c :: tail => loop( '{ Pred.single( ${ Expr(c) } ) }, tail)
loop(allChars)
case ReCast(re, cast) =>
toTyre(re) match
case '{ $ree: Tyre[t1] } => '{ Cast(${ ree }, ${ Expr(cast) }) }
Expand All @@ -106,4 +100,3 @@ private def tyreImpl(sc: Expr[StringContext], args: Expr[Seq[Any]])(using Quotes
private given ToExpr[CastOp] with
def apply(c: CastOp)(using Quotes) = c match
case CastOp.Stringify => '{ CastOp.Stringify }
case CastOp.Literal => '{ CastOp.Literal }
6 changes: 3 additions & 3 deletions src/main/scala/net/marek/tyre/pattern/StringParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ private object TyreParser extends Parsers:
escape ~> accept("predef class", { case el: Char if CharClass.hasNeg(el) => CharClass.negs(el) })
private val inBracketSpecial =
accept("not escaped special", { case el: Char if !Reserved.isEscapedInBrackets(el) => el })
private val literalCastOp = accept("literal cast operator", { case 'l' => 'l' })

private val literalInBracket = literal | inBracketSpecial

Expand All @@ -91,9 +92,8 @@ private object TyreParser extends Parsers:

private val any =
hole ^^ ReHole.apply
| lBracket ~> rep1(rangeOrLiteralInBrackets) ~ (rBracket ~> opt(exclamation ~> CastOp.Literal)) ^^ {
case list ~ Some(cast) => ReCast(ReIn(list.flatten), cast)
case list ~ None => ReIn(list.flatten)
| lBracket ~> rep1(rangeOrLiteralInBrackets) <~ rBracket ~ exclamation ~ literalCastOp ^^ { case list =>
ReLiteralConv(ReIn(list.flatten))
}
| lBracket ~> opt(caret) ~ rep1(rangeOrLiteralOrCharClassInBrackets) <~ rBracket ^^ {
case Some(_) ~ list => ReNotIn(list.flatten)
Expand Down
9 changes: 2 additions & 7 deletions src/main/scala/net/marek/tyre/pattern/TyreOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@ private object OrM:
Conv(Or(left, right), merge)

private object OrMWithSingle:
def merge[R1 <: Singleton, R2](e: Either[R1, R2]): R1 | R2 = e match
case Left(v) => v
case Right(v) => v
def apply[R1 <: Singleton, R2](left: Tyre[R1], right: Tyre[R2]): Tyre[R1 | R2] =
Conv(Or(left, right), merge)
def apply[R2](c: Char & Singleton, right: Tyre[R2]): Tyre[c.type | R2] =
OrM(Single(c), right)

private object AndF:
def apply[R, RT <: Tuple](left: Tyre[R], right: Tyre[RT]): Tyre[R *: RT] =
Expand All @@ -41,5 +38,3 @@ private object Cast:
case s => s.toString
def apply[R](re: Tyre[R], op: CastOp) = op match
case CastOp.Stringify => re.map(string)
case CastOp.Literal => ???

7 changes: 2 additions & 5 deletions src/test/scala/net/marek/tyre/ConversionTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,5 @@ class ConversionTest extends AnyFunSuite:
@unused val _: Tyre[('a', List[Char])] = tyre"[a]!l.*"
@unused val _: Tyre[('a' | 'b', List[Char])] = tyre"[ab]!l.*"
@unused val _: Tyre[('a' | 'b' | 'c', List[Char])] = tyre"[a-c]!l.*"
@unused val _: Tyre[(List['a' | 'b' | 'c'], List[Char])] = tyre"[a-c]!l*.*"
val g = 8
//assertDoesNotCompile(tyre"[a-\u3333]!l.*") // to many literal types in union


@unused val _: Tyre[(List['a' | 'b' | 'c' | 'w'], List[Char])] = tyre"[a-cw]!l*.*"
// assertDoesNotCompile(tyre"[a-\u3333]!l.*") // to many literal types in union

0 comments on commit 6d83b54

Please sign in to comment.