Skip to content

Commit

Permalink
Tweak test and fix op= precedence
Browse files Browse the repository at this point in the history
  • Loading branch information
som-snytt committed Nov 23, 2022
1 parent 63bc505 commit 0d03922
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 11 deletions.
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ object NameOps {
case raw.NE | raw.LE | raw.GE | EMPTY =>
false
case name: SimpleName =>
name.length > 0 && name.last == '=' && name.head != '=' && isOperatorPart(name.head)
name.length > 0 && name.last == '=' && name.head != '=' && isOperatorPart(name.firstCodePoint)
case _ =>
false
}
Expand Down Expand Up @@ -358,6 +358,14 @@ object NameOps {
val unmangled = kinds.foldLeft(name)(_.unmangle(_))
if (unmangled eq name) name else unmangled.unmangle(kinds)
}

def firstCodePoint: Int =
val first = name.firstPart
import Character.{isHighSurrogate, isLowSurrogate, isValidCodePoint, toCodePoint}
if isHighSurrogate(first(0)) && first.length > 1 && isLowSurrogate(first(1)) then
val codepoint = toCodePoint(first(0), first(1))
if isValidCodePoint(codepoint) then codepoint else first(0)
else first(0)
}

extension (name: TermName) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/parsing/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package object parsing {
def precedence(operator: Name): Int =
if (operator eq nme.ERROR) -1
else {
val firstCh = operator.firstPart.head
val firstCh = operator.firstCodePoint
if (isScalaLetter(firstCh)) 1
else if (operator.isOpAssignmentName) 0
else firstCh match {
Expand Down
7 changes: 7 additions & 0 deletions compiler/src/dotty/tools/dotc/util/Chars.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ object Chars:
'|' | '/' | '\\' => true
case c => isSpecial(c)
}
def isOperatorPart(c: CodePoint): Boolean = (c: @switch) match {
case '~' | '!' | '@' | '#' | '%' |
'^' | '*' | '+' | '-' | '<' |
'>' | '?' | ':' | '=' | '&' |
'|' | '/' | '\\' => true
case c => isSpecial(c)
}

/** Would the character be encoded by `NameTransformer.encode`? */
def willBeEncoded(c: Char): Boolean = !isJavaIdentifierPart(c)
23 changes: 14 additions & 9 deletions tests/run/t1406b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,20 @@ case class C(n: Int) {
def +(c: C): C = C(n + c.n)
}
object Test extends App {
val Sum = 84
val Product = 1764
val ProductSum = 1806
val SumProduct = 3528
val c, d = C(42)
println(c + d)
println(c * d)
println(c ☀ d)
println(c * d + d)
println(c ☀ d + d)
println(c ☀= d + d) // assignment op is low precedence
println(c 𐀀 d + d) // the first one, letter should be low precedence
println(c 🌀d + d) // the second one, cyclone should be high precedence
println(c 🌀= d + d) // the second one, cyclone should be high precedence
def assertEquals(expected: Int, actual: C) = assert(expected == actual.n)
assertEquals(Sum, c + d)
assertEquals(Product, c * d)
assertEquals(Product, c ☀ d)
assertEquals(ProductSum, c * d + d)
assertEquals(ProductSum, c ☀ d + d)
assertEquals(SumProduct, c ☀= d + d) // assignment op is low precedence
assertEquals(SumProduct, c 𐀀 d + d) // the first one, letter should be low precedence
assertEquals(ProductSum, c 🌀d + d) // the second one, cyclone should be high precedence
assertEquals(SumProduct, c 🌀= d + d) // assignment op is low precedence
}

0 comments on commit 0d03922

Please sign in to comment.