@@ -99,7 +99,7 @@ fileprivate extension Compiler.ByteCodeGen {
99
99
}
100
100
101
101
// Fast path for eliding boundary checks for an all ascii quoted literal
102
- if optimizationsEnabled && s. allSatisfy ( { char in char . isASCII} ) {
102
+ if optimizationsEnabled && s. allSatisfy ( \ . isASCII) {
103
103
let lastIdx = s. unicodeScalars. indices. last!
104
104
for idx in s. unicodeScalars. indices {
105
105
let boundaryCheck = idx == lastIdx
@@ -274,10 +274,13 @@ fileprivate extension Compiler.ByteCodeGen {
274
274
}
275
275
276
276
mutating func emitScalar( _ s: UnicodeScalar ) {
277
+ // A scalar in grapheme semantic mode must match a full charcter, so
278
+ // perform a boundary check
279
+ let boundaryCheck = options. semanticLevel == . graphemeCluster
277
280
if options. isCaseInsensitive && s. properties. isCased {
278
- builder. buildMatchScalarCaseInsensitive ( s, boundaryCheck: false )
281
+ builder. buildMatchScalarCaseInsensitive ( s, boundaryCheck: boundaryCheck )
279
282
} else {
280
- builder. buildMatchScalar ( s, boundaryCheck: false )
283
+ builder. buildMatchScalar ( s, boundaryCheck: boundaryCheck )
281
284
}
282
285
}
283
286
@@ -292,8 +295,12 @@ fileprivate extension Compiler.ByteCodeGen {
292
295
293
296
if options. isCaseInsensitive && c. isCased {
294
297
if optimizationsEnabled && c. isASCII {
295
- // c.isCased ensures that c is not CR-LF, so we know that c is a single scalar
296
- builder. buildMatchScalarCaseInsensitive ( c. unicodeScalars. last!, boundaryCheck: true )
298
+ // c.isCased ensures that c is not CR-LF,
299
+ // so we know that c is a single scalar
300
+ assert ( c. unicodeScalars. count == 1 )
301
+ builder. buildMatchScalarCaseInsensitive (
302
+ c. unicodeScalars. last!,
303
+ boundaryCheck: true )
297
304
} else {
298
305
builder. buildMatch ( c, isCaseInsensitive: true )
299
306
}
0 commit comments