ronantakizawa/codereview-bench huggingface dataset:
Repository: JuliaLang/julia
File: base/docs/basedocs.jl (Julia)

Code before:
"""
replaceglobal!

"""
    setglobalonce!(module::Module, name::Symbol, value,
                  [success_order::Symbol, [fail_order::Symbol=success_order]) -> success::Bool

Atomically perform the operations to set a global to
a given value, only if it was previously not set.

!!! compat "Julia 1.11"
    This function requires Julia 1.11 or later.

See also [`setpropertyonce!`](@ref Base.setpropertyonce!) and [`setglobal!`](@ref).
"""
setglobalonce!

"""
    declare_global(module::Module, name::Symbol, strong::Bool=false, [ty::Type])

Declare the global `name` in module `module`.  If `ty` is given, declares a
"strong" global, which cannot be replaced with a constant binding, otherwise
declares a weak global.

Does not update the current task's world age.

See also [`global`](@ref), [`setglobal!`](@ref), [`get_binding_type`](@ref Core.get_binding_type).
"""
Core.declare_global

"""
   _import(to::Module, from::Module, asname::Symbol, [sym::Symbol, imported::Bool])

With all five arguments, imports `sym` from module `from` into `to` with name
`asname`.  `imported` is true for bindings created with `import` (set it to
false for `using A: ...`).

With only the first three arguments, creates a binding for the module `from`
with name `asname` in `to`.
"""
Core._import

"""
   _using(to::Module, from::Module)

Add `from` to the usings list of `to`.
"""
Core._using

"""
    typeof(x)

Review comment (suggestion):
Since this is impossible for any function to do, it seems odd to call out that this function doesn't do it
```suggestion
```

Code after:
"""
replaceglobal!

"""
    setglobalonce!(module::Module, name::Symbol, value,
                  [success_order::Symbol, [fail_order::Symbol=success_order]) -> success::Bool

Atomically perform the operations to set a global to
a given value, only if it was previously not set.

!!! compat "Julia 1.11"
    This function requires Julia 1.11 or later.

See also [`setpropertyonce!`](@ref Base.setpropertyonce!) and [`setglobal!`](@ref).
"""
setglobalonce!

"""
    declare_global(module::Module, name::Symbol, strong::Bool=false, [ty::Type])

Declare the global `name` in module `module`.  If `ty` is given, declares a
"strong" global, which cannot be replaced with a constant binding, otherwise
declares a weak global.

See also [`global`](@ref), [`setglobal!`](@ref), [`get_binding_type`](@ref Core.get_binding_type).
"""
Core.declare_global

"""
    declare_const(module::Module, name::Symbol, [x])

Create or replace the constant `name` in `module` with the new value `x`.  When
replacing, `x` does not need to have the same type as the original constant.

When `x` is not given, `name` becomes an undefined constant; it cannot be read
or written to, but can be redefined.

Unlike the syntax `const`, calling this function does not insert `Core.@latestworld` to update the world age of the current frame:
```
julia> begin
           const x = 1
           println(x)
           const x = 2
           println(x)
           Core.declare_const(Main, :x, 3)
           println(x)
           Core.@latestworld
           println(x)
       end
1
2
Repository: JuliaLang/julia
File: stdlib/Base64/src/decode.jl (Julia)

Code before:
```jldoctest
julia> io = IOBuffer();

julia> iob64_decode = Base64DecodePipe(io);

julia> write(io, "SGVsbG8h")
8

julia> seekstart(io);

julia> String(read(iob64_decode))
"Hello!"
```
"""
struct Base64DecodePipe{T <: IO} <: IO
    io::T
    buffer::Buffer
    rest::Vector{UInt8}

    function Base64DecodePipe{T}(io::T) where {T <: IO}
        buffer = Buffer(512)
        return new{T}(io, buffer, UInt8[])
    end
end

Base64DecodePipe(io::IO) = Base64DecodePipe{typeof(io)}(io)

Base.isreadable(pipe::Base64DecodePipe) = !isempty(pipe.rest) || isreadable(pipe.io)
Base.iswritable(::Base64DecodePipe) = false

function Base.unsafe_read(pipe::Base64DecodePipe, ptr::Ptr{UInt8}, n::UInt)
    p = read_until_end(pipe, ptr, n)
    if p < ptr + n
        throw(EOFError())
    end
    return nothing
end

# Read and decode as much data as possible.
function read_until_end(pipe::Base64DecodePipe, ptr::Ptr{UInt8}, n::UInt)
    p = ptr
    p_end = ptr + n
    while !isempty(pipe.rest) && p < p_end
        unsafe_store!(p, popfirst!(pipe.rest))
        p += 1
    end

    buffer = pipe.buffer
    i = 0
    b1 = b2 = b3 = b4 = BASE64_CODE_IGN
    while true

Review comment (performance):
```suggestion
Base64DecodePipe(io::IO) = Base64DecodePipe{IO}(io)
```

Doesn't seem like this PR makes things faster, so by default it seems better to avoid making the compile slower and more complex?

Code after:
```jldoctest
julia> io = IOBuffer();

julia> iob64_decode = Base64DecodePipe(io);

julia> write(io, "SGVsbG8h")
8

julia> seekstart(io);

julia> String(read(iob64_decode))
"Hello!"
```
"""
struct Base64DecodePipe{T <: IO} <: IO
    io::T
    buffer::Buffer
    rest::Vector{UInt8}

    function Base64DecodePipe{T}(io::T) where {T <: IO}
        buffer = Buffer(512)
        return new{T}(io, buffer, UInt8[])
    end
end

Base64DecodePipe(io::IO) = Base64DecodePipe{IO}(io)

Base.isreadable(pipe::Base64DecodePipe) = !isempty(pipe.rest) || isreadable(pipe.io)
Base.iswritable(::Base64DecodePipe) = false

function Base.unsafe_read(pipe::Base64DecodePipe, ptr::Ptr{UInt8}, n::UInt)
    p = read_until_end(pipe, ptr, n)
    if p < ptr + n
        throw(EOFError())
    end
    return nothing
end

# Read and decode as much data as possible.
function read_until_end(pipe::Base64DecodePipe, ptr::Ptr{UInt8}, n::UInt)
    p = ptr
    p_end = ptr + n
    while !isempty(pipe.rest) && p < p_end
        unsafe_store!(p, popfirst!(pipe.rest))
        p += 1
    end

    buffer = pipe.buffer
    i = 0
    b1 = b2 = b3 = b4 = BASE64_CODE_IGN
    while true
Repository: JuliaLang/julia
File: stdlib/Base64/src/encode.jl (Julia)

Code before:
# Examples
```jldoctest
julia> io = IOBuffer();

julia> iob64_encode = Base64EncodePipe(io);

julia> write(iob64_encode, "Hello!")
6

julia> close(iob64_encode);

julia> str = String(take!(io))
"SGVsbG8h"

julia> String(base64decode(str))
"Hello!"
```
"""
struct Base64EncodePipe{T <: IO} <: IO
    io::T
    buffer::Buffer

    function Base64EncodePipe{T}(io::T) where {T <: IO}
        # The buffer size must be at least 3.
        buffer = Buffer(512)
        pipe = new{typeof(io)}(io, buffer)
        finalizer(_ -> close(pipe), buffer)
        return pipe
    end
end

Base64EncodePipe(io::IO) = Base64EncodePipe{typeof(io)}(io)

Base.isreadable(::Base64EncodePipe) = false
Base.iswritable(pipe::Base64EncodePipe) = iswritable(pipe.io)

function Base.unsafe_write(pipe::Base64EncodePipe, ptr::Ptr{UInt8}, n::UInt)::Int
    buffer = pipe.buffer
    m = buffer.size
    b1, b2, b3, k = loadtriplet!(buffer, ptr, n)
    @assert k ≥ m
    p = ptr + k - m
    if k < 3
        if k == 1
            buffer[1] = b1
            buffer.size = 1
        elseif k == 2
            buffer[1] = b1
            buffer[2] = b2
            buffer.size = 2
        end

Review comment (suggestion):
```suggestion
        pipe = new{T}(io, buffer)
```

Code after:
# Examples
```jldoctest
julia> io = IOBuffer();

julia> iob64_encode = Base64EncodePipe(io);

julia> write(iob64_encode, "Hello!")
6

julia> close(iob64_encode);

julia> str = takestring!(io)
"SGVsbG8h"

julia> String(base64decode(str))
"Hello!"
```
"""
struct Base64EncodePipe{T <: IO} <: IO
    io::T
    buffer::Buffer

    function Base64EncodePipe{T}(io::T) where {T <: IO}
        # The buffer size must be at least 3.
        buffer = Buffer(512)
        pipe = new{T}(io, buffer)
        finalizer(_ -> close(pipe), buffer)
        return pipe
    end
end

Base64EncodePipe(io::IO) = Base64EncodePipe{IO}(io)

Base.isreadable(::Base64EncodePipe) = false
Base.iswritable(pipe::Base64EncodePipe) = iswritable(pipe.io)

function Base.unsafe_write(pipe::Base64EncodePipe, ptr::Ptr{UInt8}, n::UInt)::Int
    buffer = pipe.buffer
    m = buffer.size
    b1, b2, b3, k = loadtriplet!(buffer, ptr, n)
    @assert k ≥ m
    p = ptr + k - m
    if k < 3
        if k == 1
            buffer[1] = b1
            buffer.size = 1
        elseif k == 2
            buffer[1] = b1
            buffer[2] = b2
            buffer.size = 2
        end
Repository: JuliaLang/julia
File: stdlib/Base64/src/encode.jl (Julia)

Code before:
julia> write(iob64_encode, "Hello!")
6

julia> close(iob64_encode);

julia> str = String(take!(io))
"SGVsbG8h"

julia> String(base64decode(str))
"Hello!"
```
"""
struct Base64EncodePipe{T <: IO} <: IO
    io::T
    buffer::Buffer

    function Base64EncodePipe{T}(io::T) where {T <: IO}
        # The buffer size must be at least 3.
        buffer = Buffer(512)
        pipe = new{typeof(io)}(io, buffer)
        finalizer(_ -> close(pipe), buffer)
        return pipe
    end
end

Base64EncodePipe(io::IO) = Base64EncodePipe{typeof(io)}(io)

Base.isreadable(::Base64EncodePipe) = false
Base.iswritable(pipe::Base64EncodePipe) = iswritable(pipe.io)

function Base.unsafe_write(pipe::Base64EncodePipe, ptr::Ptr{UInt8}, n::UInt)::Int
    buffer = pipe.buffer
    m = buffer.size
    b1, b2, b3, k = loadtriplet!(buffer, ptr, n)
    @assert k ≥ m
    p = ptr + k - m
    if k < 3
        if k == 1
            buffer[1] = b1
            buffer.size = 1
        elseif k == 2
            buffer[1] = b1
            buffer[2] = b2
            buffer.size = 2
        end
        return p - ptr
    end
    @assert buffer.size == 0

    i = 0
    p_end = ptr + n

Review comment (suggestion):
```suggestion
Base64EncodePipe(io::IO) = Base64EncodePipe{IO}(io)
```

Code after:
julia> write(iob64_encode, "Hello!")
6

julia> close(iob64_encode);

julia> str = takestring!(io)
"SGVsbG8h"

julia> String(base64decode(str))
"Hello!"
```
"""
struct Base64EncodePipe{T <: IO} <: IO
    io::T
    buffer::Buffer

    function Base64EncodePipe{T}(io::T) where {T <: IO}
        # The buffer size must be at least 3.
        buffer = Buffer(512)
        pipe = new{T}(io, buffer)
        finalizer(_ -> close(pipe), buffer)
        return pipe
    end
end

Base64EncodePipe(io::IO) = Base64EncodePipe{IO}(io)

Base.isreadable(::Base64EncodePipe) = false
Base.iswritable(pipe::Base64EncodePipe) = iswritable(pipe.io)

function Base.unsafe_write(pipe::Base64EncodePipe, ptr::Ptr{UInt8}, n::UInt)::Int
    buffer = pipe.buffer
    m = buffer.size
    b1, b2, b3, k = loadtriplet!(buffer, ptr, n)
    @assert k ≥ m
    p = ptr + k - m
    if k < 3
        if k == 1
            buffer[1] = b1
            buffer.size = 1
        elseif k == 2
            buffer[1] = b1
            buffer[2] = b2
            buffer.size = 2
        end
        return p - ptr
    end
    @assert buffer.size == 0

    i = 0
    p_end = ptr + n
Repository: JuliaLang/julia
File: test/core.jl (Julia)

Code before:
    using .M2
    export x
end
@test M57638_3.x === 1

module GlobalBindingMulti
    module M
        export S
        module C
            export S
            struct A end
            S = A() # making S const makes the error go away
        end
        using .C
    end

    using .M
    using .M.C
end
@test GlobalBindingMulti.S === GlobalBindingMulti.M.C.S

#58434 bitsegal comparison of oddly sized fields
primitive type ByteString58434 (18 * 8) end

@test Base.datatype_isbitsegal(Tuple{ByteString58434}) == false
@test Base.datatype_haspadding(Tuple{ByteString58434}) == true


Review comment (suggestion):
```suggestion
@test Base.datatype_haspadding(Tuple{ByteString58434}) == (length(Base.padding(Tuple{ByteString58434})) > 0) 
```

Might be good as a sanity check to ensure that reflection stays consistent with this, since this fluctuated in the past.

Code after:
    using .M2
    export x
end
@test M57638_3.x === 1

module GlobalBindingMulti
    module M
        export S
        module C
            export S
            struct A end
            S = A() # making S const makes the error go away
        end
        using .C
    end

    using .M
    using .M.C
end
@test GlobalBindingMulti.S === GlobalBindingMulti.M.C.S

#58434 bitsegal comparison of oddly sized fields
primitive type ByteString58434 (18 * 8) end

@test Base.datatype_isbitsegal(Tuple{ByteString58434}) == false
@test Base.datatype_haspadding(Tuple{ByteString58434}) == (length(Base.padding(Tuple{ByteString58434})) > 0)
Repository: JuliaLang/julia
File: test/core.jl (Julia)

Code before:
    using .M2
    export x
end
@test M57638_3.x === 1

module GlobalBindingMulti
    module M
        export S
        module C
            export S
            struct A end
            S = A() # making S const makes the error go away
        end
        using .C
    end

    using .M
    using .M.C
end
@test GlobalBindingMulti.S === GlobalBindingMulti.M.C.S

#58434 bitsegal comparison of oddly sized fields
primitive type ByteString58434 (18 * 8) end

@test Base.datatype_isbitsegal(Tuple{ByteString58434}) == false
@test Base.datatype_haspadding(Tuple{ByteString58434}) == (length(Base.padding(Tuple{ByteString58434})) > 0) 


Review comment (suggestion):
```suggestion
@test Base.datatype_haspadding(Tuple{ByteString58434}) == (length(Base.padding(Tuple{ByteString58434})) > 0)
```

Code after:
    using .M2
    export x
end
@test M57638_3.x === 1

module GlobalBindingMulti
    module M
        export S
        module C
            export S
            struct A end
            S = A() # making S const makes the error go away
        end
        using .C
    end

    using .M
    using .M.C
end
@test GlobalBindingMulti.S === GlobalBindingMulti.M.C.S

#58434 bitsegal comparison of oddly sized fields
primitive type ByteString58434 (18 * 8) end

@test Base.datatype_isbitsegal(Tuple{ByteString58434}) == false
@test Base.datatype_haspadding(Tuple{ByteString58434}) == (length(Base.padding(Tuple{ByteString58434})) > 0)
Repository: JuliaLang/julia
File: base/summarysize.jl (Julia)

Code before:
                    value = unwrap_unionall(value)
                end
                if isa(value, DataType) && parentmodule(value) === obj && nameof(value) === binding
                    # charge a TypeName to its module (but not to the type)
                    size += ss(value.name)::Int
                end
            end
        end
    end
    return size
end

function (ss::SummarySize)(obj::Task)
    haskey(ss.seen, obj) ? (return 0) : (ss.seen[obj] = true)
    size::Int = (ss.count ? 1 : Core.sizeof(obj))
    if isdefined(obj, :code)
        size += ss(obj.code)::Int
    end
    size += ss(obj.storage)::Int
    size += ss(obj.donenotify)::Int
    size += ss(obj.result)::Int
    # TODO: add stack size, and possibly traverse stack roots
    return size
end

(ss::SummarySize)(obj::BigInt) = _summarysize(ss, obj, ss.count) + obj.alloc * (ss.count ? 1 : sizeof(Base.GMP.Limb))


Review comment (suggestion):
```suggestion
(ss::SummarySize)(obj::BigInt) = _summarysize(ss, obj, ss.count) + (ss.count ? 1 : obj.alloc * sizeof(Base.GMP.Limb))
```

Code after:
                end
                if isa(value, DataType) && parentmodule(value) === obj && nameof(value) === binding
                    # charge a TypeName to its module (but not to the type)
                    size += ss(value.name)::Int
                end
            end
        end
    end
    return size
end

function (ss::SummarySize)(obj::Task)
    haskey(ss.seen, obj) ? (return 0) : (ss.seen[obj] = true)
    size::Int = (ss.count ? 1 : Core.sizeof(obj))
    if isdefined(obj, :code)
        size += ss(obj.code)::Int
    end
    size += ss(obj.storage)::Int
    size += ss(obj.donenotify)::Int
    size += ss(obj.result)::Int
    # TODO: add stack size, and possibly traverse stack roots
    return size
end

(ss::SummarySize)(obj::BigInt) = _summarysize(ss, obj, ss.count) + (ss.count ? 1 : obj.alloc * sizeof(GMP.Limb))
Repository: JuliaLang/julia
File: base/summarysize.jl (Julia)

Code before:
                    value = unwrap_unionall(value)
                end
                if isa(value, DataType) && parentmodule(value) === obj && nameof(value) === binding
                    # charge a TypeName to its module (but not to the type)
                    size += ss(value.name)::Int
                end
            end
        end
    end
    return size
end

function (ss::SummarySize)(obj::Task)
    haskey(ss.seen, obj) ? (return 0) : (ss.seen[obj] = true)
    size::Int = (ss.count ? 1 : Core.sizeof(obj))
    if isdefined(obj, :code)
        size += ss(obj.code)::Int
    end
    size += ss(obj.storage)::Int
    size += ss(obj.donenotify)::Int
    size += ss(obj.result)::Int
    # TODO: add stack size, and possibly traverse stack roots
    return size
end

(ss::SummarySize)(obj::BigInt) = _summarysize(ss, obj, ss.count) + obj.alloc * (ss.count ? 1 : sizeof(GMP.Limb))


Review comment (suggestion):
```suggestion
(ss::SummarySize)(obj::BigInt) = _summarysize(ss, obj, ss.count) + (ss.count ? 1 : obj.alloc * sizeof(GMP.Limb))
```

Code after:
                end
                if isa(value, DataType) && parentmodule(value) === obj && nameof(value) === binding
                    # charge a TypeName to its module (but not to the type)
                    size += ss(value.name)::Int
                end
            end
        end
    end
    return size
end

function (ss::SummarySize)(obj::Task)
    haskey(ss.seen, obj) ? (return 0) : (ss.seen[obj] = true)
    size::Int = (ss.count ? 1 : Core.sizeof(obj))
    if isdefined(obj, :code)
        size += ss(obj.code)::Int
    end
    size += ss(obj.storage)::Int
    size += ss(obj.donenotify)::Int
    size += ss(obj.result)::Int
    # TODO: add stack size, and possibly traverse stack roots
    return size
end

(ss::SummarySize)(obj::BigInt) = _summarysize(ss, obj, ss.count) + (ss.count ? 1 : obj.alloc * sizeof(GMP.Limb))
Repository: JuliaLang/julia
File: test/syntax.jl (Julia)

Code before:
            $(Expr(:thisfunction))
        end
        inner_func
    end

    let cs = CallableStruct2()
        @test cs()() === cs()
        @test cs()() !== cs
    end

    # Keywords
    let
        @eval f2(; n=1) = n <= 1 ? n : n * $(Expr(:thisfunction))(; n=n-1)
        result = f2(n=5)
        @test result == 120
    end

    # Struct constructor with thisfunction
    let
        @eval struct Cols{T<:Tuple}
            cols::T
            operator
            Cols(args...; operator=union) = (new{typeof(args)}(args, operator); string($(Expr(:thisfunction))))
        end
        result = Cols(1, 2, 3)
        @test result == "Cols"
    end
end


Review comment (suggestion):
```suggestion
        @test occursin("Cols", result)
```

Code after:

    @testset "Closures and nested functions" begin
        # Prevents boxed closures
        function make_closure()
            fib(n) = n <= 1 ? 1 : (@__FUNCTION__)(n - 1) + (@__FUNCTION__)(n - 2)
            return fib
        end
        Test.@inferred make_closure()
        closure = make_closure()
        @test closure(5) == 8
        Test.@inferred closure(5)

        # Complex closure of closures
        function f1()
            function f2()
                function f3()
                    return @__FUNCTION__
                end
                return (@__FUNCTION__), f3()
            end
            return (@__FUNCTION__), f2()...
        end
        Test.@inferred f1()
        @test f1()[1] === f1
        @test f1()[2] !== f1
        @test f1()[3] !== f1
        @test f1()[3]() === f1()[3]
        @test f1()[2]()[2]() === f1()[3]
    end

    @testset "Do blocks" begin
        function test_do_block()
            result = map([1, 2, 3]) do x
                return (@__FUNCTION__, x)
            end
            # All should refer to the same do-block function
            @test all(r -> r[1] === result[1][1], result)
            # Values should be different
            @test [r[2] for r in result] == [1, 2, 3]
            # It should be different than `test_do_block`
            @test result[1][1] !== test_do_block
        end
        test_do_block()
    end

    @testset "Keyword arguments" begin
        # @__FUNCTION__ with kwargs
        foo(; n) = n <= 1 ? 1 : n * (@__FUNCTION__)(; n = n - 1)
        @test foo(n = 5) == 120

        # Expr(:thisfunction) with kwargs
Repository: JuliaLang/julia
File: test/trimming/hello.jl (Julia)

Code before:
    side::Float64
end
struct Circle <: Shape
    radius::Float64
end
area(s::Square) = s.side^2
area(c::Circle) = pi*c.radius^2

sum_areas(v::Vector{Shape}) = sum(area, v)

function @main(args::Vector{String})::Cint
    println(Core.stdout, str())
    foreach(x->println(Core.stdout, x), args)

    # test map/mapreduce; should work but relies on inlining and other optimizations
    # test that you can dispatch to some number of concrete cases
    println(Core.stdout, sum_areas(Shape[Circle(1), Square(2)]))

    arr = rand(10)
    sorted_arr = sort(arr)
    tot = sum(sorted_arr)
    tot = prod(sorted_arr)
    a = any(x -> x > 0, sorted_arr)
    b = all(x -> x >= 0, sorted_arr)
    c = map(x -> x^2, sorted_arr)
    # d = mapreduce(x -> x^2, +, sorted_arr) this doesn't work because of mapreduce_empty_iter having F specialized
    # e = reduce(xor, rand(Int, 10))
    return 0
end


Review comment (suggestion):
This one now works for me locally!

```suggestion
    d = mapreduce(x -> x^2, +, sorted_arr)
```

Code after:
    side::Float64
end
struct Circle <: Shape
    radius::Float64
end
area(s::Square) = s.side^2
area(c::Circle) = pi*c.radius^2

sum_areas(v::Vector{Shape}) = sum(area, v)

function @main(args::Vector{String})::Cint
    println(Core.stdout, str())
    foreach(x->println(Core.stdout, x), args)

    # test map/mapreduce; should work but relies on inlining and other optimizations
    # test that you can dispatch to some number of concrete cases
    println(Core.stdout, sum_areas(Shape[Circle(1), Square(2)]))

    arr = rand(10)
    sorted_arr = sort(arr)
    tot = sum(sorted_arr)
    tot = prod(sorted_arr)
    a = any(x -> x > 0, sorted_arr)
    b = all(x -> x >= 0, sorted_arr)
    c = map(x -> x^2, sorted_arr)
    d = mapreduce(x -> x^2, +, sorted_arr)
    # e = reduce(xor, rand(Int, 10))
    return 0
end
Repository: JuliaLang/julia
File: test/trimming/libsimple.jl (Julia)

Code before:
struct MyTwoVec
    x::Int32
    y::Int32
end

Base.@ccallable "copyto_and_sum" function badname(fromto::CVectorPair{Float32})::Float32
    from, to = unsafe_wrap(Array, fromto.from.data, fromto.from.length), unsafe_wrap(Array, fromto.to.data, fromto.to.length)
    copyto!(to, from)
    return sum(to)
end

Base.@ccallable function countsame(list::Ptr{MyTwoVec}, n::Int32)::Int32
    list = unsafe_wrap(Array, list, n)
    count = 0
    for v in list
        count += v.x == v.y
    end
    return count
end

export countsame, copyto_and_sum

# FIXME? varargs
# Base.@ccallable function printints(x::Cint...)::Nothing
#     for i in 1:length(x)
#         print(x[i], " ")
#     end
#     println()
# end

end


Review comment (suggestion):
Two slightly advanced (but important) features:
  - `Ref{...}` should be supported in addition to `Ptr{...}`
  - function pointers are just `Ptr{Cvoid}` ABI-wise but for C to be able to call them, we do need to export type definitions for them

Code after:
struct MyTwoVec
    x::Int32
    y::Int32
end

struct CTree{T}
    # test that recursive datatypes work as expected
    children::CVector{CTree{T}}
end

Base.@ccallable "tree_size" function size(tree::CTree{Float64})::Int64
    children = unsafe_wrap(Array, tree.children.data, tree.children.length)
    # Return the size of this sub-tree
    return sum(Int64[
        size(child)
        for child in children
    ]; init=1)
end

Base.@ccallable "copyto_and_sum" function badname(fromto::CVectorPair{Float32})::Float32
    from, to = unsafe_wrap(Array, fromto.from.data, fromto.from.length), unsafe_wrap(Array, fromto.to.data, fromto.to.length)
    copyto!(to, from)
    return sum(to)
end

Base.@ccallable function countsame(list::Ptr{MyTwoVec}, n::Int32)::Int32
    list = unsafe_wrap(Array, list, n)
    count = 0
    for v in list
        count += v.x == v.y
    end
    return count
end

export countsame, copyto_and_sum

# FIXME? varargs
# Base.@ccallable function printints(x::Cint...)::Nothing
#     for i in 1:length(x)
#         print(x[i], " ")
#     end
#     println()
# end

end