Skip to content

Commit

Permalink
Add compiletime.ops.string.CharAt
Browse files Browse the repository at this point in the history
  • Loading branch information
OlivierBlanvillain committed Feb 8, 2022
1 parent 74c2954 commit f08e8c0
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 1 deletion.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,7 @@ class Definitions {
)
private val compiletimePackageBooleanTypes: Set[Name] = Set(tpnme.Not, tpnme.Xor, tpnme.And, tpnme.Or)
private val compiletimePackageStringTypes: Set[Name] = Set(
tpnme.Plus, tpnme.Length, tpnme.Substring, tpnme.Matches
tpnme.Plus, tpnme.Length, tpnme.Substring, tpnme.Matches, tpnme.CharAt
)
private val compiletimePackageOpTypes: Set[Name] =
Set(tpnme.S)
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ object StdNames {
final val Plus: N = "+"
final val S: N = "S"
final val Substring: N = "Substring"
final val CharAt: N = "CharAt"
final val Times: N = "*"
final val ToInt: N = "ToInt"
final val ToLong: N = "ToLong"
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4423,6 +4423,8 @@ object Types {
case tpnme.Matches => constantFold2(stringValue, _ matches _)
case tpnme.Substring =>
constantFold3(stringValue, intValue, intValue, (s, b, e) => s.substring(b, e))
case tpnme.CharAt =>
constantFold2AB(stringValue, intValue, _ charAt _)
case _ => None
} else if (owner == defn.CompiletimeOpsBooleanModuleClass) name match {
case tpnme.Not => constantFold1(boolValue, x => !x)
Expand Down
11 changes: 11 additions & 0 deletions library/src/scala/compiletime/ops/string.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,14 @@ object string:
*/
@experimental
type Matches[S <: String, Regex <: String] <: Boolean

/** Returns the Char type at the specified index.
* An index ranges from 0 to Length[S] - 1. The first Char of
* the sequence is at index 0, the next at index 1, and so on.
* ```scala
* val c: CharAt["hello", 0] = 'h'
* ```
* @syntax markdown
*/
@experimental
type CharAt[S <: String, Idx <: Int] <: Char
19 changes: 19 additions & 0 deletions tests/neg/singleton-ops-string.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,23 @@ object Test {

val t9: Matches["hamburger", "ham.*"] = true
val t10: Matches["hamburger", "ham.*"] = false // error

val t11: CharAt["String", 0] = 'S'
val t12: CharAt["String", 1] = 't'
val t13: CharAt["String", 2] = '!' // error
// ^^^
// Found: ('!' : Char)
// Required: ('r' : Char)
val t14: CharAt["String", 3] = '!' // error
// ^^^
// Found: ('!' : Char)
// Required: ('i' : Char)
val t15: CharAt["String", 4] = 'n'
val t16: CharAt["String", 5] = 'g'
val t17: CharAt["String", 6] = '!' // error
// ^
// String index out of range: 6
val t18: CharAt["String", -1] = '?' // error
// ^
// String index out of range: -1
}

0 comments on commit f08e8c0

Please sign in to comment.