|
| 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 |
0 commit comments