forked from JuliaInterop/RCall.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
types.jl
340 lines (282 loc) · 8.07 KB
/
types.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
@doc """
R symbolic expression (`SxpPtr`): these are represented by a pointer to a
symbolic expression record (`Sxp`).
"""->
abstract Sxp # SEXPREC
typealias SxpPtr{S<:Sxp} Ptr{S} # SEXP
typealias SxpPtrInfo UInt32 # sxpinfo_struct
@doc "R Sxp header: a pointer to this is used for unknown types."->
immutable SxpHead <: Sxp # SEXPREC_HEADER
info::SxpPtrInfo
attrib::Ptr{SxpHead}
gc_next::Ptr{SxpHead}
gc_prev::Ptr{SxpHead}
end
typealias UnknownSxpPtr Ptr{SxpHead}
abstract VectorSxp <: Sxp
abstract VectorAtomicSxp <: VectorSxp
abstract VectorNumericSxp <: VectorAtomicSxp
abstract VectorListSxp <: VectorSxp
abstract PairListSxp <: Sxp
abstract FunctionSxp <: Sxp
@doc "R NULL value"->
immutable NilSxp <: PairListSxp # type tag 0
head::SxpHead
end
typealias NilSxpPtr Ptr{NilSxp}
@doc "R pairs (cons) list cell"->
immutable ListSxp <: PairListSxp # type tag 2
head::SxpHead
car::UnknownSxpPtr
cdr::UnknownSxpPtr
tag::UnknownSxpPtr
end
typealias ListSxpPtr Ptr{ListSxp}
@doc "R function closure"->
immutable ClosSxp <: FunctionSxp # type tag 3
head::SxpHead
formals::ListSxpPtr
body::UnknownSxpPtr
env::UnknownSxpPtr
end
typealias ClosSxpPtr Ptr{ClosSxp}
@doc "R environment"->
immutable EnvSxp <: Sxp # type tag 4
head::SxpHead
frame::UnknownSxpPtr
enclos::UnknownSxpPtr
hashtab::UnknownSxpPtr
end
typealias EnvSxpPtr Ptr{EnvSxp}
@doc "R promise"->
immutable PromSxp <: Sxp # type tag 5
head::SxpHead
value::UnknownSxpPtr
expr::UnknownSxpPtr
env::UnknownSxpPtr
end
typealias PromSxpPtr Ptr{PromSxp}
@doc "R function call"->
immutable LangSxp <: PairListSxp # type tag 6
head::SxpHead
car::UnknownSxpPtr
cdr::UnknownSxpPtr
tag::UnknownSxpPtr
end
typealias LangSxpPtr Ptr{LangSxp}
@doc "R special function"->
immutable SpecialSxp <: FunctionSxp # type tag 7
head::SxpHead
end
typealias SpecialSxpPtr Ptr{SpecialSxp}
@doc "R built-in function"->
immutable BuiltinSxp <: FunctionSxp # type tag 8
head::SxpHead
end
typealias BuiltinSxpPtr Ptr{BuiltinSxp}
@doc "R character string"->
immutable CharSxp <: VectorAtomicSxp # type tag 9
head::SxpHead
length::Cint
truelength::Cint
end
typealias CharSxpPtr Ptr{CharSxp}
@doc "R symbol"->
immutable SymSxp <: Sxp # type tag 1
head::SxpHead
name::CharSxpPtr
value::UnknownSxpPtr
internal::UnknownSxpPtr
end
typealias SymSxpPtr Ptr{SymSxp}
@doc "R logical vector"->
immutable LglSxp <: VectorNumericSxp # type tag 10
head::SxpHead
length::Cint
truelength::Cint
end
typealias LglSxpPtr Ptr{LglSxp}
@doc "R integer vector"->
immutable IntSxp <: VectorNumericSxp # type tag 13
head::SxpHead
length::Cint
truelength::Cint
end
typealias IntSxpPtr Ptr{IntSxp}
@doc "R real vector"->
immutable RealSxp <: VectorNumericSxp # type tag 14
head::SxpHead
length::Cint
truelength::Cint
end
typealias RealSxpPtr Ptr{RealSxp}
@doc "R complex vector"->
immutable CplxSxp <: VectorNumericSxp # type tag 15
head::SxpHead
length::Cint
truelength::Cint
end
typealias CplxSxpPtr Ptr{CplxSxp}
@doc "R vector of character strings"->
immutable StrSxp <: VectorListSxp # type tag 16
head::SxpHead
length::Cint
truelength::Cint
end
typealias StrSxpPtr Ptr{StrSxp}
@doc "R dot-dot-dot object"->
immutable DotSxp <: Sxp # type tag 17
head::SxpHead
end
typealias DotSxpPtr Ptr{DotSxp}
@doc "R \"any\" object"->
immutable AnySxp <: Sxp # type tag 18
head::SxpHead
end
typealias AnySxpPtr Ptr{AnySxp}
@doc "R list (i.e. Array{Any,1})"->
immutable VecSxp <: VectorListSxp # type tag 19
head::SxpHead
length::Cint
truelength::Cint
end
typealias VecSxpPtr Ptr{VecSxp}
@doc "R expression vector"->
immutable ExprSxp <: VectorListSxp # type tag 20
head::SxpHead
length::Cint
truelength::Cint
end
typealias ExprSxpPtr Ptr{ExprSxp}
@doc "R byte code"->
immutable BcodeSxp <: Sxp # type tag 21
head::SxpHead
end
typealias BcodeSxpPtr Ptr{BcodeSxp}
@doc "R external pointer"->
immutable ExtPtrSxp <: Sxp # type tag 22
head::SxpHead
ptr::Ptr{Void}
prot::Ptr{Void}
tag::UnknownSxpPtr
end
typealias ExtPtrSxpPtr Ptr{ExtPtrSxp}
@doc "R weak reference"->
immutable WeakRefSxp <: Sxp # type tag 23
head::SxpHead
end
typealias WeakRefSxpPtr Ptr{WeakRefSxp}
@doc "R byte vector"->
immutable RawSxp <: VectorAtomicSxp # type tag 24
head::SxpHead
length::Cint
truelength::Cint
end
typealias RawSxpPtr Ptr{RawSxp}
@doc "R S4 object"->
immutable S4Sxp <: Sxp # type tag 25
head::SxpHead
end
typealias S4SxpPtr Ptr{S4Sxp}
typealias VectorSxpPtr{S<:VectorSxp} Ptr{S}
typealias VectorAtomicSxpPtr{S<:VectorAtomicSxp} Ptr{S}
typealias VectorNumericSxpPtr{S<:VectorNumericSxp} Ptr{S}
typealias VectorListSxpPtr{S<:VectorListSxp} Ptr{S}
typealias PairListSxpPtr{S<:PairListSxp} Ptr{S}
typealias FunctionSxpPtr{S<:FunctionSxp} Ptr{S}
@doc """
Element types of R vectors.
"""->
eltype(::Type{LglSxp}) = Cint
eltype(::Type{IntSxp}) = Cint
eltype(::Type{RealSxp}) = Float64
eltype(::Type{CplxSxp}) = Complex128
eltype(::Type{CharSxp}) = UInt8
eltype(::Type{RawSxp}) = UInt8
eltype(::Type{StrSxp}) = Ptr{CharSxp}
eltype(::Type{VecSxp}) = UnknownSxpPtr
eltype(::Type{ExprSxp}) = UnknownSxpPtr
@doc """
An `RObject` is a Julia wrapper for an R object (known as an "S-expression" or "SEXP"). It is stored as a pointer which is protected from the R garbage collector, until the `RObject` itself is finalized by Julia. The parameter is the type of the S-expression.
When called with a Julia object as an argument, a corresponding R object is constructed.
```julia
julia> RObject(1)
RObject{IntSxp}
[1] 1
julia> RObject(1:3)
RObject{IntSxp}
[1] 1 2 3
julia> RObject(1.0:3.0)
RObject{RealSxp}
[1] 1 2 3
```
"""->
type RObject{S<:Sxp}
p::Ptr{S}
function RObject(p::Ptr{S})
preserve(p)
r = new(p)
finalizer(r, release)
r
end
# SymSxps are not garbage collected, so preserve not necessary.
RObject(p::Ptr{SymSxp}) = new(p)
end
RObject{S<:Sxp}(p::Ptr{S}) = RObject{S}(p)
RObject(x::RObject) = x
RObject(x) = RObject(sexp(x))
# convert{T}(::Type{T}, r::RObject) = convert(T,r.p)
@doc """
Prevent garbage collection of an R object. Object can be released via `release`.
This is slower than `protect`, as it requires searching an internal list, but
more flexible.
"""->
preserve{S<:Sxp}(p::Ptr{S}) = ccall((:R_PreserveObject,libR), Void, (Ptr{S},), p)
@doc """
Release object that has been gc protected by `preserve`.
"""->
release{S<:Sxp}(p::Ptr{S}) = ccall((:R_ReleaseObject,libR),Void,(Ptr{S},),p)
release{S<:Sxp}(r::RObject{S}) = release(r.p)
@doc """
Stack-based protection of garbage collection of R objects. Objects are
released via `unprotect`. Returns the same pointer, allowing inline use.
This is faster than `preserve`, but more restrictive. Really only useful
inside functions.
"""->
protect{S<:Sxp}(p::Ptr{S}) = ccall((:Rf_protect,libR), Ptr{S}, (Ptr{S},), p)
@doc """
Release last `n` objects gc-protected by `protect`.
"""->
unprotect(n::Integer) = ccall((:Rf_unprotect,libR), Void, (Cint,), n)
@doc """
The SEXPTYPE number of a `Sxp`
Determined from the trailing 5 bits of the first 32-bit word. Is
a 0-based index into the `info` field of a `SxpHead`.
"""->
sexpnum(h::SxpHead) = h.info & 0x1f
sexpnum(p::SxpPtr) = sexpnum(unsafe_load(p))
@doc "vector of R Sxp types"->
const typs = [NilSxp,SymSxp,ListSxp,ClosSxp,EnvSxp,
PromSxp,LangSxp,SpecialSxp,BuiltinSxp,CharSxp,
LglSxp,Void,Void,IntSxp,RealSxp,
CplxSxp,StrSxp,DotSxp,AnySxp,VecSxp,
ExprSxp,BcodeSxp,ExtPtrSxp,WeakRefSxp,RawSxp,
S4Sxp]
for (i,T) in enumerate(typs)
if T != Void
@eval sexpnum(::Type{$T}) = $(i-1)
end
end
@doc """
Convert a `UnknownSxpPtr` to an approptiate `SxpPtr`.
"""->
function sexp(p::UnknownSxpPtr)
typ = sexpnum(p)
0 ≤ typ ≤ 10 || 13 ≤ typ ≤ 25 || error("Unknown SEXPTYPE $typ")
styp = typs[typ+1]
convert(Ptr{styp},p)
end
sexp(s::SxpPtr) = s
sexp(r::RObject) = r.p
sexp{S<:Sxp}(::Type{S},s::Ptr{S}) = s
sexp{S<:Sxp}(::Type{S},r::RObject{S}) = r.p