Skip to content

Commit 22f11cd

Browse files
committed
Tweak test and fix op= precedence
1 parent 91cca71 commit 22f11cd

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-11
lines changed

compiler/src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ object NameOps {
104104
case raw.NE | raw.LE | raw.GE | EMPTY =>
105105
false
106106
case name: SimpleName =>
107-
name.length > 0 && name.last == '=' && name.head != '=' && isOperatorPart(name.head)
107+
name.length > 0 && name.last == '=' && name.head != '=' && isOperatorPart(name.firstCodePoint)
108108
case _ =>
109109
false
110110
}
@@ -358,6 +358,14 @@ object NameOps {
358358
val unmangled = kinds.foldLeft(name)(_.unmangle(_))
359359
if (unmangled eq name) name else unmangled.unmangle(kinds)
360360
}
361+
362+
def firstCodePoint: Int =
363+
val first = name.firstPart
364+
import Character.{isHighSurrogate, isLowSurrogate, isValidCodePoint, toCodePoint}
365+
if isHighSurrogate(first(0)) && first.length > 1 && isLowSurrogate(first(1)) then
366+
val codepoint = toCodePoint(first(0), first(1))
367+
if isValidCodePoint(codepoint) then codepoint else first(0)
368+
else first(0)
361369
}
362370

363371
extension (name: TermName) {

compiler/src/dotty/tools/dotc/parsing/package.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ package object parsing {
1717
def precedence(operator: Name): Int =
1818
if (operator eq nme.ERROR) -1
1919
else {
20-
val firstCh = operator.firstPart.head
20+
val firstCh = operator.firstCodePoint
2121
if (isScalaLetter(firstCh)) 1
2222
else if (operator.isOpAssignmentName) 0
2323
else firstCh match {

compiler/src/dotty/tools/dotc/util/Chars.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ object Chars:
100100
'|' | '/' | '\\' => true
101101
case c => isSpecial(c)
102102
}
103+
def isOperatorPart(c: CodePoint): Boolean = (c: @switch) match {
104+
case '~' | '!' | '@' | '#' | '%' |
105+
'^' | '*' | '+' | '-' | '<' |
106+
'>' | '?' | ':' | '=' | '&' |
107+
'|' | '/' | '\\' => true
108+
case c => isSpecial(c)
109+
}
103110

104111
/** Would the character be encoded by `NameTransformer.encode`? */
105112
def willBeEncoded(c: Char): Boolean = !isJavaIdentifierPart(c)

tests/run/t1406b.scala

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,20 @@ case class C(n: Int) {
99
def +(c: C): C = C(n + c.n)
1010
}
1111
object Test extends App {
12+
val Sum = 84
13+
val Product = 1764
14+
val ProductSum = 1806
15+
val SumProduct = 3528
1216
val c, d = C(42)
13-
println(c + d)
14-
println(c * d)
15-
println(c d)
16-
println(c * d + d)
17-
println(c d + d)
18-
println(c ☀= d + d) // assignment op is low precedence
19-
println(c 𐀀 d + d) // the first one, letter should be low precedence
20-
println(c 🌀d + d) // the second one, cyclone should be high precedence
21-
println(c 🌀= d + d) // the second one, cyclone should be high precedence
17+
def assertEquals(expected: Int, actual: C) = assert(expected == actual.n)
18+
assertEquals(Sum, c + d)
19+
assertEquals(Product, c * d)
20+
assertEquals(Product, c d)
21+
assertEquals(ProductSum, c * d + d)
22+
assertEquals(ProductSum, c d + d)
23+
assertEquals(SumProduct, c ☀= d + d) // assignment op is low precedence
24+
assertEquals(SumProduct, c 𐀀 d + d) // the first one, letter should be low precedence
25+
assertEquals(ProductSum, c 🌀d + d) // the second one, cyclone should be high precedence
26+
assertEquals(SumProduct, c 🌀= d + d) // assignment op is low precedence
2227
}
2328

0 commit comments

Comments
 (0)