-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathinterface.jl
97 lines (76 loc) · 2.55 KB
/
interface.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""
Interface{Components}
Abstract supertype for all Interfaces.jl interfaces.
Components is an `Tuple` of `Symbol`.
"""
abstract type Interface{Components} end
"""
optional_keys(T::Type{<:Interface}, O::Type)
Get the keys for the optional components of an [`Interface`](@ref),
as a tuple os `Symbol`.
"""
function optional_keys end
optional_keys(T::Type{<:Interface}, obj) = optional_keys(T, typeof(obj))
optional_keys(T::Type{<:Interface}, obj::Type) = ()
optional_keys(T::Type{<:Interface}) = keys(components(T).optional)
mandatory_keys(T::Type{<:Interface}, args...) = keys(components(T).mandatory)
"""
test_objects(T::Type{<:Interface}, O::Type)
Get the test object(s) for type `O` and interface `T`.
"""
function test_objects end
"""
description(::Type{<:Interface})
Returns a `String` description of an interface.
"""
function description end
"""
components(::Type{<:Interface})
Returns the components of the interface, as a `NamedTuple` of `NamedTuple`.
"""
function components end
"""
requiredtype(::Type{<:Interface})
Returns the supertype required for all interface implementations.
"""
function requiredtype end
"""
@interface(interfacename, components, [description])
Define an interface that can apply to types `<: Any`.
```julia
components = (
mandatory = (
length = x -> length(x) = prod(size(x)),
ndims = x -> ndims(x) = length(size(x)),
),
optional = (;)
)
description = "A description of the interface"
@interface MyInterface Any components description
```
"""
macro interface(interface::Symbol, type, components, description)
quote
@assert $type isa Type
@assert $components isa NamedTuple{(:mandatory,:optional)}
@assert $description isa String
# Define the interface type (should it be concrete?)
abstract type $interface{Components} <: $Interfaces.Interface{Components} end
# Define the interface component methods
$Interfaces.requiredtype(::Type{<:$interface}) = $type
$Interfaces.components(::Type{<:$interface}) = $components
$Interfaces.description(::Type{<:$interface}) = $description
# Generate a docstring for the interface
let description=$description,
interfacesym=$(QuoteNode(interface)),
header=$Interfaces._help_header($interface),
extended_help=$Interfaces._extended_help($interface)
@doc """
$(" ") $interfacesym
$header
$description
$extended_help
""" $interface
end
end |> esc
end