From b802fea9a995bf2b1183be8211f2d9eb97c407a5 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Fri, 3 May 2024 16:22:33 +0530 Subject: [PATCH 1/4] Assume :foldable in isuppercase/islowercase for Char --- base/strings/unicode.jl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/base/strings/unicode.jl b/base/strings/unicode.jl index a3b06063b98ac..de01890fdaf79 100644 --- a/base/strings/unicode.jl +++ b/base/strings/unicode.jl @@ -5,7 +5,8 @@ module Unicode import Base: show, ==, hash, string, Symbol, isless, length, eltype, convert, isvalid, ismalformed, isoverlong, iterate, - AnnotatedString, AnnotatedChar, annotated_chartransform + AnnotatedString, AnnotatedChar, annotated_chartransform, + @assume_effects # whether codepoints are valid Unicode scalar values, i.e. 0-0xd7ff, 0xe000-0x10ffff @@ -385,7 +386,10 @@ julia> islowercase('❤') false ``` """ -islowercase(c::AbstractChar) = ismalformed(c) ? false : Bool(ccall(:utf8proc_islower, Cint, (UInt32,), UInt32(c))) +islowercase(c::AbstractChar) = _islowercase(c) +# identical method body, but with better effects for a Char argument +@assume_effects :foldable islowercase(c::Char) = _islowercase(c) +@inline _islowercase(c) = ismalformed(c) ? false : Bool(ccall(:utf8proc_islower, Cint, (UInt32,), UInt32(c))) # true for Unicode upper and mixed case @@ -409,7 +413,10 @@ julia> isuppercase('❤') false ``` """ -isuppercase(c::AbstractChar) = ismalformed(c) ? false : Bool(ccall(:utf8proc_isupper, Cint, (UInt32,), UInt32(c))) +isuppercase(c::AbstractChar) = _isuppercase(c) +# identical method body, but with better effects for a Char argument +@assume_effects :foldable isuppercase(c::Char) = _isuppercase(c) +@inline _isuppercase(c) = ismalformed(c) ? false : Bool(ccall(:utf8proc_isupper, Cint, (UInt32,), UInt32(c))) """ iscased(c::AbstractChar) -> Bool From 4fc39d4e02fbc92143c65a57d8b1bbd7782f5d12 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Mon, 6 May 2024 21:53:22 +0530 Subject: [PATCH 2/4] Only annotate ccall --- base/strings/unicode.jl | 24 ++++++++++++++++-------- test/char.jl | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/base/strings/unicode.jl b/base/strings/unicode.jl index de01890fdaf79..2619d9877652b 100644 --- a/base/strings/unicode.jl +++ b/base/strings/unicode.jl @@ -386,10 +386,14 @@ julia> islowercase('❤') false ``` """ -islowercase(c::AbstractChar) = _islowercase(c) -# identical method body, but with better effects for a Char argument -@assume_effects :foldable islowercase(c::Char) = _islowercase(c) -@inline _islowercase(c) = ismalformed(c) ? false : Bool(ccall(:utf8proc_islower, Cint, (UInt32,), UInt32(c))) +function islowercase(c::AbstractChar) + if ismalformed(c) + false + else + ui = UInt32(c)::UInt32 # type-assertion to ensure that we may assume :foldable + @assume_effects :foldable Bool(ccall(:utf8proc_islower, Cint, (UInt32,), ui)) + end +end # true for Unicode upper and mixed case @@ -413,10 +417,14 @@ julia> isuppercase('❤') false ``` """ -isuppercase(c::AbstractChar) = _isuppercase(c) -# identical method body, but with better effects for a Char argument -@assume_effects :foldable isuppercase(c::Char) = _isuppercase(c) -@inline _isuppercase(c) = ismalformed(c) ? false : Bool(ccall(:utf8proc_isupper, Cint, (UInt32,), UInt32(c))) +function isuppercase(c::AbstractChar) + if ismalformed(c) + false + else + ui = UInt32(c)::UInt32 # type-assertion to ensure that we may assume :foldable + @assume_effects :foldable Bool(ccall(:utf8proc_isupper, Cint, (UInt32,), ui)) + end +end """ iscased(c::AbstractChar) -> Bool diff --git a/test/char.jl b/test/char.jl index 1d3579013ad18..5a522dfd1c743 100644 --- a/test/char.jl +++ b/test/char.jl @@ -360,3 +360,21 @@ end @test Base.IteratorSize(Char) == Base.HasShape{0}() @test convert(ASCIIChar, 1) == Char(1) end + +@testset "foldable isuppercase/islowercase" begin + v = @inferred (() -> Val(isuppercase('C')))() + @test v isa Val{true} + v = @inferred (() -> Val(islowercase('C')))() + @test v isa Val{false} + + struct MyChar <: AbstractChar + x :: Char + end + Base.codepoint(m::MyChar) = codepoint(m.x) + MyChar(x::UInt32) = MyChar(Char(x)) + + v = @inferred (() -> Val(isuppercase(MyChar('C'))))() + @test v isa Val{true} + v = @inferred (() -> Val(islowercase(MyChar('C'))))() + @test v isa Val{false} +end From 6acb90da1f1dd61af424337083bd1b3933883551 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 7 May 2024 10:41:52 +0530 Subject: [PATCH 3/4] Update base/strings/unicode.jl Annotate `@ccall` macro Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> --- base/strings/unicode.jl | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/base/strings/unicode.jl b/base/strings/unicode.jl index 2619d9877652b..b8864cdf3e588 100644 --- a/base/strings/unicode.jl +++ b/base/strings/unicode.jl @@ -386,14 +386,8 @@ julia> islowercase('❤') false ``` """ -function islowercase(c::AbstractChar) - if ismalformed(c) - false - else - ui = UInt32(c)::UInt32 # type-assertion to ensure that we may assume :foldable - @assume_effects :foldable Bool(ccall(:utf8proc_islower, Cint, (UInt32,), ui)) - end -end +islowercase(c::AbstractChar) = ismalformed(c) ? false : + Bool(@assume_effects :foldable @ccall utf8proc_islower(UInt32(c)::UInt32)::Cint) # true for Unicode upper and mixed case From c362cb345e42fa8772582225af78707652abb23a Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 7 May 2024 10:42:14 +0530 Subject: [PATCH 4/4] Update base/strings/unicode.jl Annotate `@ccall` macro in `isuppercase` Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> --- base/strings/unicode.jl | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/base/strings/unicode.jl b/base/strings/unicode.jl index b8864cdf3e588..cc02412925d14 100644 --- a/base/strings/unicode.jl +++ b/base/strings/unicode.jl @@ -411,14 +411,8 @@ julia> isuppercase('❤') false ``` """ -function isuppercase(c::AbstractChar) - if ismalformed(c) - false - else - ui = UInt32(c)::UInt32 # type-assertion to ensure that we may assume :foldable - @assume_effects :foldable Bool(ccall(:utf8proc_isupper, Cint, (UInt32,), ui)) - end -end +isuppercase(c::AbstractChar) = ismalformed(c) ? false : + Bool(@assume_effects :foldable @ccall utf8proc_isupper(UInt32(c)::UInt32)::Cint) """ iscased(c::AbstractChar) -> Bool