-
Notifications
You must be signed in to change notification settings - Fork 0
/
typedecls-extract.jl
85 lines (81 loc) · 2.71 KB
/
typedecls-extract.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
#######################################################################
# Extracting type declarations from the source code
###############################
#
# The goal is to extract user-defined type declarations,
# in particular, declared supertypes.
#
# Here, we are not interested in type annotations on fields,
# because those are processed by types-extract.jl.
#
#######################################################################
"""
:: Any → TypeDeclInfoList
Collects type declarations in `expr`
"""
collectTypeDeclarations(expr) :: TypeDeclInfoList = begin
tyDecls = nil(TypeDeclInfo)
recordTyDecls(e) = begin
try
(e, tyDecls) = collectTypeDeclaration(e, tyDecls)
catch err
@error "Couldn't process expression" e err
end
e # return for `prewalk` to work
end
MacroTools.prewalk(recordTyDecls, expr)
tyDecls
end
"""
:: (Any, TypeDeclInfoList) → (Any, TypeDeclInfoList)
If `expr` is not a type declaration, returns:
- `expr` as is
- `tyDecls` as is
Otherwise, returns:
- the empty expression `:()`
- the type declaration represented by `expr` concatenated with `tyDecls``
"""
collectTypeDeclaration(expr, tyDecls :: TypeDeclInfoList) = begin
kind = tdabst
tyDecl = :()
tySuper = :Any
# TD stands for the declaration itself,
# S stands for the declared supertype,
# F stands for fields
# E.g. `Foo{X} <: Bar` => TD is Foo{X}, S is Bar.
# If no supertype is provided, tySuper defaults to Any]
if @capture(expr, abstract type TD_ <: S_ end)
(kind, tyDecl, tySuper) = (tdabst, TD, S)
elseif @capture(expr, abstract type TD_ end)
(kind, tyDecl) = (tdabst, TD)
elseif @capture(expr, primitive type TD_ <: S_ B_ end)
(kind, tyDecl, tySuper) = (tdprim, TD, S)
elseif @capture(expr, primitive type TD_ B_ end)
(kind, tyDecl) = (tdprim, TD)
elseif @capture(expr, mutable struct TD_ <: S_ F_ end)
(kind, tyDecl, tySuper) = (tdmtbl, TD, S)
elseif @capture(expr, mutable struct TD_ F_ end)
(kind, tyDecl) = (tdmtbl, TD)
elseif @capture(expr, struct TD_ <: S_ F_ end)
(kind, tyDecl, tySuper) = (tdstrc, TD, S)
elseif @capture(expr, struct TD_ F_ end)
(kind, tyDecl,) = (tdstrc, TD)
else
return (expr, tyDecls)
end
# We also want to extract info about arguments
name = Symbol("<NA-typename>")
if @capture(tyDecl, N_{ARGS__})
name = N
else
if tyDecl isa Symbol
name = tyDecl
else
@error "type declaration $tyDecl is expected to be a Symbol"
end
end
( :(),
cons(TypeDeclInfo(
name, kind, tyDecl, tySuper
), tyDecls))
end