-
Notifications
You must be signed in to change notification settings - Fork 6
/
utils.jl
76 lines (66 loc) · 2.06 KB
/
utils.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
macro __splatnew__(T, args)
esc(Expr(:splatnew, T, args))
end
"""
__new__(T, args...)
User-level version of the `new()` pseudofunction.
Can be used to construct most Julia types, including structs
without default constructors, closures, etc.
"""
@generated __new__(T, x...) = Expr(:new, :T, map(n -> :(x[$n]), 1:length(x))...)
function __splatnew__(T, t)
return __new__(T, t...)
end
"""
function __foreigncall__(
::Val{name}, ::Val{RT}, AT::Tuple, ::Val{nreq}, ::Val{calling_convention}, x...
) where {name, RT, nreq, calling_convention}
:foreigncall nodes get translated into calls to this function.
For example,
```julia
Expr(:foreigncall, :foo, Tout, (A, B), nreq, :ccall, args...)
```
becomes
```julia
__foreigncall__(Val(:foo), Val(Tout), (Val(A), Val(B)), Val(nreq), Val(:ccall), args...)
```
Please consult the Julia documentation for more information on how foreigncall nodes work,
and consult this package's tests for examples.
"""
@generated function __foreigncall__(
::Val{name}, ::Val{RT}, AT::Tuple, ::Val{nreq}, ::Val{calling_convention}, x...
) where {name, RT, nreq, calling_convention}
return Expr(
:foreigncall,
QuoteNode(name),
:($(RT)),
Expr(:call, :(Core.svec), map(__get_arg_type, AT.parameters)...),
:($nreq),
QuoteNode(calling_convention),
map(n -> :(x[$n]), 1:length(x))...,
)
end
__get_arg_type(::Type{Val{T}}) where {T} = T
"""
Unwrap constant value from its expression container such as
GlobalRef, QuoteNode, etc. No-op if there's no known container.
"""
promote_const_value(x::QuoteNode) = x.value
promote_const_value(x::GlobalRef) = getproperty(x.mod, x.name)
promote_const_value(x) = x
function module_of(f, args...)
if f isa Core.IntrinsicFunction || f isa Core.Builtin
# may be actually another built-in module, but it's ok for our use case
return Core
else
types = map(Core.Typeof, args)
return which(f, types).module
end
end
function flatten(xs)
res = []
for x in xs
append!(res, x)
end
return res
end