Skip to content

Commit 7abc461

Browse files
authored
Initial implementation (#1)
1 parent 6cb7adb commit 7abc461

File tree

4 files changed

+99
-3
lines changed

4 files changed

+99
-3
lines changed

src/BackendSelection.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module BackendSelection
22

3-
# Write your package code here.
3+
include("abstractbackend.jl")
4+
include("backend_types.jl")
45

56
end

src/abstractbackend.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
abstract type AbstractBackend end
2+
3+
backend_string(::AbstractBackend) = error("Not implemented")
4+
parameters(::AbstractBackend) = error("Not implemented")

src/backend_types.jl

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
macro generate_backend_type(type::Symbol)
2+
return generate_backend_type_expr(type)
3+
end
4+
5+
function generate_backend_type_expr(type::Symbol)
6+
return esc(
7+
quote
8+
"""
9+
$($type)
10+
11+
A type representing a backend for a function.
12+
13+
For example, a function might have multiple backends
14+
implementations, which internally are selected with a `$($type)` type.
15+
16+
This allows users to extend functionality with a new implementation but
17+
use the same interface.
18+
"""
19+
struct $type{Back,Kwargs<:NamedTuple} <: AbstractBackend
20+
kwargs::Kwargs
21+
end
22+
23+
$type{Back}(kwargs::NamedTuple) where {Back} = $type{Back,typeof(kwargs)}(kwargs)
24+
$type{Back}(; kwargs...) where {Back} = $type{Back}(NamedTuple(kwargs))
25+
$type(s; kwargs...) = $type{Symbol(s)}(NamedTuple(kwargs))
26+
27+
$type(backend::$type) = backend
28+
29+
# TODO: Use `SetParameters`.
30+
backend_string(::$type{Back}) where {Back} = string(Back)
31+
parameters(backend::$type) = getfield(backend, :kwargs)
32+
33+
Base.getproperty(backend::$type, name::Symbol) = parameters(backend)[name]
34+
Base.propertynames(backend::$type) = propertynames(parameters(backend))
35+
36+
function Base.show(io::IO, backend::$type)
37+
return print(
38+
io, "$($type) type ", backend_string(backend), ", ", parameters(backend)
39+
)
40+
end
41+
function Base.print(io::IO, backend::$type)
42+
return print(io, backend_string(backend), ", ", parameters(backend))
43+
end
44+
end,
45+
)
46+
end
47+
48+
@generate_backend_type Algorithm
49+
@generate_backend_type Backend
50+
51+
function backend_macro_docstring(backend)
52+
return """
53+
@$(backend)_str
54+
55+
A convenience macro for writing [`$backend`](@ref) types, typically used when
56+
adding methods to a function that supports multiple backends.
57+
"""
58+
end
59+
60+
# TODO: See if these can be moved inside of `@eval`.
61+
"""
62+
$(backend_macro_docstring(:Algorithm))
63+
"""
64+
macro Algorithm_str(s)
65+
return :(Algorithm{$(Expr(:quote, Symbol(s)))})
66+
end
67+
68+
"""
69+
$(backend_macro_docstring(:Backend))
70+
"""
71+
macro Backend_str(s)
72+
return :(Backend{$(Expr(:quote, Symbol(s)))})
73+
end

test/test_basics.jl

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
1-
using BackendSelection: BackendSelection
1+
using BackendSelection: BackendSelection, @Algorithm_str, @Backend_str, Algorithm, Backend
22
using Test: @test, @testset
33

44
@testset "BackendSelection" begin
5-
# Tests go here.
5+
for type in (Algorithm, Backend)
6+
@testset "$type" begin
7+
@test type("backend") isa type{:backend}
8+
@test type(:backend) isa type{:backend}
9+
backend = type("backend"; x=2, y=3)
10+
@test backend isa type{:backend}
11+
@test backend.x == 2
12+
@test backend.y == 3
13+
@test propertynames(backend) == (:x, :y)
14+
(; x, y) = backend
15+
@test x == 2
16+
@test y == 3
17+
@test BackendSelection.parameters(backend) === (; x=2, y=3)
18+
end
19+
end
20+
# Macro syntax.
21+
@test Algorithm"backend"(; x=2, y=3) === Algorithm("backend"; x=2, y=3)
22+
@test Backend"backend"(; x=2, y=3) === Backend("backend"; x=2, y=3)
23+
@test isnothing(show(Algorithm("")))
624
end

0 commit comments

Comments
 (0)