galaaz 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +32 -0
  3. data/Rakefile +177 -0
  4. data/bin/galaaz +8 -0
  5. data/examples/50Plots_MasterList/scatter_plot.rb +51 -0
  6. data/examples/baseball.csv +1 -0
  7. data/examples/baseball.rb +16 -0
  8. data/examples/ggplot.rb +178 -0
  9. data/examples/islr/Figure.jpg +0 -0
  10. data/examples/islr/all.rb +32 -0
  11. data/examples/islr/ch2.spec.rb +148 -0
  12. data/examples/islr/ch3.spec.rb +28 -0
  13. data/examples/islr/ch3_boston.rb +77 -0
  14. data/examples/islr/ch3_multiple_regression.rb +36 -0
  15. data/examples/islr/ch6.spec.rb +64 -0
  16. data/examples/paper/paper.rb +36 -0
  17. data/examples/sthda_ggplot/README.md +38 -0
  18. data/examples/sthda_ggplot/all.rb +68 -0
  19. data/examples/sthda_ggplot/one_variable_continuous/density_gg.rb +52 -0
  20. data/examples/sthda_ggplot/one_variable_continuous/geom_area.rb +61 -0
  21. data/examples/sthda_ggplot/one_variable_continuous/geom_density.rb +77 -0
  22. data/examples/sthda_ggplot/one_variable_continuous/geom_dotplot.rb +69 -0
  23. data/examples/sthda_ggplot/one_variable_continuous/geom_freqpoly.rb +69 -0
  24. data/examples/sthda_ggplot/one_variable_continuous/geom_histogram.rb +62 -0
  25. data/examples/sthda_ggplot/one_variable_continuous/histogram_density.rb +55 -0
  26. data/examples/sthda_ggplot/one_variable_continuous/stat.rb +62 -0
  27. data/examples/sthda_ggplot/one_variable_discrete/bar.rb +54 -0
  28. data/examples/sthda_ggplot/qplots/box_violin_dot.rb +57 -0
  29. data/examples/sthda_ggplot/qplots/scatter_plots.rb +67 -0
  30. data/examples/sthda_ggplot/scatter_gg.rb +60 -0
  31. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_bin2d.rb +49 -0
  32. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_density2d.rb +64 -0
  33. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_hex.rb +52 -0
  34. data/examples/sthda_ggplot/two_variables_cont_cont/geom_point.rb +65 -0
  35. data/examples/sthda_ggplot/two_variables_cont_cont/geom_smooth.rb +66 -0
  36. data/examples/sthda_ggplot/two_variables_cont_cont/misc.rb +83 -0
  37. data/examples/sthda_ggplot/two_variables_cont_function/geom_area.rb +63 -0
  38. data/examples/sthda_ggplot/two_variables_disc_cont/geom_bar.rb +85 -0
  39. data/examples/sthda_ggplot/two_variables_disc_cont/geom_boxplot.rb +62 -0
  40. data/examples/sthda_ggplot/two_variables_disc_cont/geom_dotplot.rb +75 -0
  41. data/examples/sthda_ggplot/two_variables_disc_cont/geom_jitter.rb +74 -0
  42. data/examples/sthda_ggplot/two_variables_disc_cont/geom_line.rb +55 -0
  43. data/examples/sthda_ggplot/two_variables_disc_cont/geom_violin.rb +70 -0
  44. data/examples/sthda_ggplot/two_variables_disc_disc/geom_jitter.rb +40 -0
  45. data/examples/sthda_ggplot/two_variables_error/geom_crossbar.rb +108 -0
  46. data/examples/subsetting.rb +372 -0
  47. data/lib/expression.rb +45 -0
  48. data/lib/galaaz.rb +27 -0
  49. data/lib/r.rb +118 -0
  50. data/lib/r_methods.rb +89 -0
  51. data/lib/rbinary_operators.rb +226 -0
  52. data/lib/rclosure.rb +34 -0
  53. data/lib/rdata_frame.rb +63 -0
  54. data/lib/renvironment.rb +34 -0
  55. data/lib/rexpression.rb +34 -0
  56. data/lib/rindexed_object.rb +68 -0
  57. data/lib/rlanguage.rb +64 -0
  58. data/lib/rlist.rb +72 -0
  59. data/lib/rmatrix.rb +38 -0
  60. data/lib/rmd_indexed_object.rb +43 -0
  61. data/lib/robject.rb +297 -0
  62. data/lib/rpkg.rb +53 -0
  63. data/lib/rsupport.rb +292 -0
  64. data/lib/rsupport_scope.rb +77 -0
  65. data/lib/rsymbol.rb +57 -0
  66. data/lib/ruby_callback.rb +83 -0
  67. data/lib/ruby_extensions.rb +74 -0
  68. data/lib/runary_operators.rb +58 -0
  69. data/lib/rvector.rb +117 -0
  70. data/r_requires/ggplot.rb +31 -0
  71. data/specs/all.rb +45 -0
  72. data/specs/r_dataframe.spec.rb +181 -0
  73. data/specs/r_eval.spec.rb +164 -0
  74. data/specs/r_function.spec.rb +105 -0
  75. data/specs/r_language.spec.rb +135 -0
  76. data/specs/r_list.spec.rb +129 -0
  77. data/specs/r_list_apply.spec.rb +99 -0
  78. data/specs/r_matrix.spec.rb +83 -0
  79. data/specs/r_vector_creation.spec.rb +99 -0
  80. data/specs/r_vector_functions.spec.rb +59 -0
  81. data/specs/r_vector_object.spec.rb +94 -0
  82. data/specs/r_vector_operators.spec.rb +174 -0
  83. data/specs/r_vector_subsetting.spec.rb +136 -0
  84. data/specs/tmp.rb +134 -0
  85. data/version.rb +2 -0
  86. metadata +198 -0
@@ -0,0 +1,297 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ##########################################################################################
4
+ # @author Rodrigo Botafogo
5
+ #
6
+ # Copyright © 2018 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
7
+ # and distribute this software and its documentation, without fee and without a signed
8
+ # licensing agreement, is hereby granted, provided that the above copyright notice, this
9
+ # paragraph and the following two paragraphs appear in all copies, modifications, and
10
+ # distributions.
11
+ #
12
+ # IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
13
+ # INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
14
+ # THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
15
+ # POSSIBILITY OF SUCH DAMAGE.
16
+ #
17
+ # RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
19
+ # SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
20
+ # RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
21
+ # OR MODIFICATIONS.
22
+ ##########################################################################################
23
+
24
+ require_relative 'r_methods'
25
+
26
+ module R
27
+
28
+ #--------------------------------------------------------------------------------------
29
+ #
30
+ #--------------------------------------------------------------------------------------
31
+
32
+ class Object
33
+
34
+ attr_reader :r_interop
35
+ attr_accessor :statement
36
+
37
+ #--------------------------------------------------------------------------------------
38
+ #
39
+ #--------------------------------------------------------------------------------------
40
+
41
+ def initialize(r_interop)
42
+ @r_interop = r_interop
43
+ end
44
+
45
+ #--------------------------------------------------------------------------------------
46
+ #
47
+ #--------------------------------------------------------------------------------------
48
+
49
+ def as__data__frame
50
+ R.as__data__frame.call(@r_interop)
51
+ end
52
+
53
+ #--------------------------------------------------------------------------------------
54
+ # @param r_interop [Interop] pointer to an R object
55
+ # @return the R object wrapped in a Ruby class
56
+ #--------------------------------------------------------------------------------------
57
+
58
+ def self.build(r_interop)
59
+
60
+ # if the value is actually not an r_interop, then just return it: native Ruby
61
+ # object
62
+ if (!Truffle::Interop.foreign?(r_interop))
63
+ return r_interop
64
+ # a matrix is also a vector... test should come before
65
+ elsif (R::Support.eval("is.matrix").call(r_interop) == true)
66
+ Matrix.new(r_interop)
67
+ elsif (R::Support.eval("is.atomic").call(r_interop) == true)
68
+ Vector.new(r_interop)
69
+ elsif (R::Support.eval("is.function").call(r_interop) == true)
70
+ Closure.new(r_interop)
71
+ elsif (R::Support.eval("is.data.frame").call(r_interop) == true)
72
+ DataFrame.new(r_interop)
73
+ elsif (R::Support.eval("is.list").call(r_interop) == true)
74
+ List.new(r_interop)
75
+ elsif (R::Support.eval("typeof").call(r_interop) == "language")
76
+ Language.new(r_interop)
77
+ elsif (R::Support.eval("typeof").call(r_interop) == "expression")
78
+ RExpression.new(r_interop)
79
+ elsif (R::Support.eval("typeof").call(r_interop) == "name")
80
+ p "i'm of type name"
81
+ Name.new(r_interop)
82
+ elsif (R::Support.eval("typeof").call(r_interop) == "symbol")
83
+ RSymbol.new(r_interop)
84
+ elsif (R::Support.eval("typeof").call(r_interop) == "environment")
85
+ Environment.new(r_interop)
86
+ else # Generic type
87
+ p "Generic type: #{R::Support.eval("typeof").call(r_interop).to_s}"
88
+ r_interop
89
+ end
90
+
91
+ end
92
+
93
+ #--------------------------------------------------------------------------------------
94
+ #
95
+ #--------------------------------------------------------------------------------------
96
+
97
+ def method_missing_assign(column_name, arg)
98
+ return setR_name("`[<-`", R.empty_symbol, column_name, arg)
99
+ end
100
+
101
+ #--------------------------------------------------------------------------------------
102
+ #
103
+ #--------------------------------------------------------------------------------------
104
+
105
+ def method_missing(symbol, *args, &block)
106
+
107
+ name = R::Support.convert_symbol2r(symbol)
108
+
109
+ case
110
+ when block_given?
111
+ R::Support.new_scope(symbol, self, *args, &block)
112
+ when name =~ /(.*)=$/
113
+ method_missing_assign($1, args[0])
114
+ when name == "eval"
115
+ # R function 'eval' needs to be called in a special way, since it expects
116
+ # the second argument to be an environment. If the arguments are packed
117
+ # into a list, then there is no second argument and the function fails to
118
+ # use the second argument as environment
119
+ R::Support.r_evaluate(r_interop, *args)
120
+ when args.length == 0
121
+ # no arguments: 2 options: either a named item of the object or apply the function
122
+ # to the object
123
+ # if name is a named item of the object, then return the named item
124
+ named = R::Support.eval("`%in%`").
125
+ call(name, R::Support.eval("names").call(@r_interop))
126
+ (false === named || !(true === named || named[0])) ?
127
+ R::Support.exec_function_name(name, @r_interop) :
128
+ R::Support.exec_function_name("`[[`", @r_interop, name)
129
+ else
130
+ args.unshift(@r_interop)
131
+ R::Support.exec_function_name(name, *args)
132
+ end
133
+
134
+ end
135
+
136
+ #----------------------------------------------------------------------------------------
137
+ # We use the following notation to access binary R functions such as %in%:
138
+ # R.vec_ "in", list.
139
+ # @param args [Array] The first element of the array is an R infix function, the other
140
+ # arguments are the list of arguments for the function.
141
+ #----------------------------------------------------------------------------------------
142
+
143
+ def _(*args)
144
+ name = "`%#{args.shift.to_s}%`"
145
+ args.unshift(@r_interop)
146
+ R::Support.exec_function_name(name, *args)
147
+ end
148
+
149
+ #--------------------------------------------------------------------------------------
150
+ # Sets the current object self interop pointer to the returned value of the execution
151
+ # of the given method with arguments. This method should be called when R will copy
152
+ # the parameter, but in Ruby we want to hide the copying.
153
+ # @param [Interop] Interop pointer to R function
154
+ # @param [Array] Array of arguments
155
+ #--------------------------------------------------------------------------------------
156
+
157
+ def setR(method, *args)
158
+ @r_interop = R::Support.exec_function_i(method, @r_interop, *args)
159
+ self
160
+ end
161
+
162
+ #--------------------------------------------------------------------------------------
163
+ #
164
+ #--------------------------------------------------------------------------------------
165
+
166
+ def setR_name(method_name, *args)
167
+ method = R::Support.eval(method_name)
168
+ setR(method, *args)
169
+ self
170
+ end
171
+
172
+ #--------------------------------------------------------------------------------------
173
+ # Sets the names attribute of the object
174
+ # @param [R::Object] names_vector is an RVector with the list of names.
175
+ #--------------------------------------------------------------------------------------
176
+
177
+ def names=(names_vector)
178
+ setR_name("`names<-`", names_vector)
179
+ end
180
+
181
+ def names(*args)
182
+ return R::Support.exec_function_name("names", @r_interop) if (args.length == 0)
183
+ setR_name("`names<-`", *args)
184
+ self
185
+ end
186
+
187
+ #--------------------------------------------------------------------------------------
188
+ #
189
+ #--------------------------------------------------------------------------------------
190
+
191
+ def rclass=(class_name)
192
+ setR_name("`class<-`", class_name)
193
+ end
194
+
195
+ def rclass
196
+ R::Support.exec_function_name("class", @r_interop)
197
+ end
198
+
199
+ #--------------------------------------------------------------------------------------
200
+ #
201
+ #--------------------------------------------------------------------------------------
202
+
203
+ def comment=(comment_text)
204
+ setR_name("`comment<-`", comment_text)
205
+ end
206
+
207
+ def comment
208
+ R::Support.exec_function_name("comment", @r_interop)
209
+ end
210
+
211
+ #--------------------------------------------------------------------------------------
212
+ #
213
+ #--------------------------------------------------------------------------------------
214
+
215
+ def dim=(numeric_vector)
216
+ setR_name("`dim<-`", numeric_vector)
217
+ end
218
+
219
+ def dim
220
+ R::Support.exec_function_name("dim", @r_interop)
221
+ end
222
+
223
+ #--------------------------------------------------------------------------------------
224
+ #
225
+ #--------------------------------------------------------------------------------------
226
+
227
+ def dimnames=(names_vector)
228
+ setR_name("`dimnames<-`", names_vector)
229
+ end
230
+
231
+ def dimnames
232
+ R::Support.exec_function_name("dimnames", @r_interop)
233
+ end
234
+
235
+ #--------------------------------------------------------------------------------------
236
+ # @bug Needed to create method R.row__names because dispatch is not working properly
237
+ #--------------------------------------------------------------------------------------
238
+
239
+ def row__names
240
+ R::Support.exec_function(R::Support.get_row_names, @r_interop)
241
+ end
242
+
243
+ # since we need to call a method and the method changes the object, then we need to
244
+ # change our internal pointer also @r_interop. Ideally, just setting the row.names
245
+ # should work.
246
+ def row__names=(names_vector)
247
+ @r_interop = R::Support.set_row_names.call(@r_interop, names_vector.r_interop)
248
+ self
249
+ end
250
+
251
+ #--------------------------------------------------------------------------------------
252
+ #
253
+ #--------------------------------------------------------------------------------------
254
+
255
+ def tsp=(numeric_vector)
256
+ setR_name("`tsp<-`", numeric_vector)
257
+ end
258
+
259
+ def tsp
260
+ R::Support.exec_function_name("tsp", @r_interop)
261
+ end
262
+
263
+ #--------------------------------------------------------------------------------------
264
+ #
265
+ #--------------------------------------------------------------------------------------
266
+
267
+ def attr=(which: w, value: v)
268
+ value = (R::Support.interop(value) ? value.r_interop : value)
269
+ # setR(@@set_attr, which, value)
270
+ setR_name("`attr<-`", which, value)
271
+ end
272
+
273
+ #--------------------------------------------------------------------------------------
274
+ #
275
+ #--------------------------------------------------------------------------------------
276
+
277
+ def pp
278
+ R.print(r_interop)
279
+ end
280
+
281
+ #--------------------------------------------------------------------------------------
282
+ #
283
+ #--------------------------------------------------------------------------------------
284
+
285
+ def to_s
286
+ cap = R::Support.capture.call(r_interop)
287
+ str = String.new
288
+ (0...(cap.size - 1)).each do |i|
289
+ str << cap[i] << "\n"
290
+ end
291
+ str << cap[cap.size - 1] if cap.size >= 1
292
+ str
293
+ end
294
+
295
+ end
296
+
297
+ end
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ##########################################################################################
4
+ # @author Rodrigo Botafogo
5
+ #
6
+ # Copyright © 2018 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
7
+ # and distribute this software and its documentation, without fee and without a signed
8
+ # licensing agreement, is hereby granted, provided that the above copyright notice, this
9
+ # paragraph and the following two paragraphs appear in all copies, modifications, and
10
+ # distributions.
11
+ #
12
+ # IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
13
+ # INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
14
+ # THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
15
+ # POSSIBILITY OF SUCH DAMAGE.
16
+ #
17
+ # RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
19
+ # SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
20
+ # RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
21
+ # OR MODIFICATIONS.
22
+ ##########################################################################################
23
+
24
+
25
+ module R
26
+
27
+ #----------------------------------------------------------------------------------------
28
+ #
29
+ #----------------------------------------------------------------------------------------
30
+
31
+ class Pkg
32
+
33
+ def initialize(pkg_name)
34
+ @pkg_name = pkg_name
35
+ end
36
+
37
+ def method_missing(symbol, *args)
38
+ p "execute #{@pkg_name}.#{symbol}(#{args})"
39
+ end
40
+
41
+ end
42
+
43
+ #----------------------------------------------------------------------------------------
44
+ #
45
+ #----------------------------------------------------------------------------------------
46
+
47
+ def self.const_missing(name)
48
+ p name
49
+ Pkg.new(name)
50
+ end
51
+
52
+ end
53
+
@@ -0,0 +1,292 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ##########################################################################################
4
+ # @author Rodrigo Botafogo
5
+ #
6
+ # Copyright © 2018 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
7
+ # and distribute this software and its documentation, without fee and without a signed
8
+ # licensing agreement, is hereby granted, provided that the above copyright notice, this
9
+ # paragraph and the following two paragraphs appear in all copies, modifications, and
10
+ # distributions.
11
+ #
12
+ # IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
13
+ # INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
14
+ # THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
15
+ # POSSIBILITY OF SUCH DAMAGE.
16
+ #
17
+ # RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
19
+ # SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
20
+ # RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
21
+ # OR MODIFICATIONS.
22
+ ##########################################################################################
23
+
24
+
25
+ module R
26
+
27
+ #--------------------------------------------------------------------------------------
28
+ # The empty_symbol is necessary to represent indexing with a missing argument such
29
+ # as [x, ]. What follows the ',' is an empty_symbol. Whenever we use in Ruby the
30
+ # :all symbol, it will be converted to an empty_symbol in R.
31
+ #--------------------------------------------------------------------------------------
32
+
33
+ @@empty_symbol = Polyglot.eval("R", <<-R)
34
+ __missing_arg = quote(f(,0));
35
+ __missing_arg[[2]]
36
+ R
37
+
38
+ def self.empty_symbol
39
+ @@empty_symbol
40
+ end
41
+
42
+ # When evaluating to NA, Interop treats it as FALSE. This breaks all expectations
43
+ # about NA. We need to protect NA from Interop unboxing. Class NotAvailable
44
+ # puts a list around NA, so that no unboxing occurs.
45
+ @na = Polyglot.eval("R", <<-R)
46
+ list(NA)
47
+ R
48
+
49
+ class NotAvailable < R::Object
50
+ end
51
+
52
+ NA = NotAvailable.new(@na)
53
+
54
+ #--------------------------------------------------------------------------------------
55
+ # This is a support module for evaluating R functions
56
+ #--------------------------------------------------------------------------------------
57
+
58
+ module Support
59
+
60
+ # Using this method gives us more control over what happens when calling do.call
61
+ # and allows for debugging. Use it in exec_function when debugging is needed.
62
+ @@exec_from_ruby = Polyglot.eval("R", <<-R)
63
+ function(build_method, ...) {
64
+ # print(build_method);
65
+ # args = list(...);
66
+ # print(args);
67
+ res = do.call(...);
68
+ # print(res);
69
+ res2 = build_method(res);
70
+ # print(res2);
71
+ res2
72
+ }
73
+ R
74
+
75
+ #----------------------------------------------------------------------------------------
76
+ # Evaluates an R code
77
+ # @param string [String] A string of R code that can be correctly parsed by R
78
+ #----------------------------------------------------------------------------------------
79
+
80
+ def self.eval(string)
81
+ Polyglot.eval("R", string)
82
+ end
83
+
84
+ #----------------------------------------------------------------------------------------
85
+ # @param object [Object] Any Ruby object
86
+ # @return boolean if the object is an interop or not
87
+ #----------------------------------------------------------------------------------------
88
+
89
+ def self.interop(object)
90
+ Truffle::Interop.foreign?(object)
91
+ end
92
+
93
+ #----------------------------------------------------------------------------------------
94
+ # @param arg [Object] A Ruby object to be converted to R to be used by an R function, or
95
+ # whatever needs it
96
+ # @return Object that can be used in R
97
+ #----------------------------------------------------------------------------------------
98
+
99
+ def self.parse_arg(arg)
100
+
101
+ case(arg)
102
+ when Truffle::Interop
103
+ arg
104
+ when R::Object
105
+ arg.r_interop
106
+ when NegRange
107
+ final_value = (arg.exclude_end?)? (arg.last - 1) : arg.last
108
+ R::Support.eval("seq").call(arg.first, final_value)
109
+ when Range
110
+ final_value = (arg.exclude_end?)? (arg.last - 1) : arg.last
111
+ R::Support.eval("seq").call(arg.first, final_value)
112
+ when :all
113
+ R.empty_symbol
114
+ when Symbol
115
+ arg = R::Support.eval("as.name").call(arg.to_s)
116
+ when Proc, Method
117
+ R::RubyCallback.build(arg)
118
+ else
119
+ arg
120
+ end
121
+
122
+ end
123
+
124
+ #----------------------------------------------------------------------------------------
125
+ # Parses the Ruby arguments into a R list of R objects
126
+ # @param args [Ruby Parameter list]
127
+ #----------------------------------------------------------------------------------------
128
+
129
+ def self.parse2list(*args)
130
+
131
+ params = Polyglot.eval("R", "list()")
132
+
133
+ args.each_with_index do |arg, i|
134
+ if (arg.is_a? Hash)
135
+ arg.each_pair do |key, value|
136
+ k = key.to_s.gsub(/__/,".")
137
+ # HAS CHANGED IN RC6... FIX THIS TO THE NEW API
138
+ # When evaluating to NA, Interop treats it as FALSE. This breaks
139
+ # all expectations about NA. We need to protect NA from Interop
140
+ # unboxing. Class NotAvailable
141
+ # puts a list around NA, so that no unboxing occurs. We need to treat this
142
+ # list here
143
+ if (value.is_a? NotAvailable)
144
+ # add the key as the name of the NA
145
+ na_named = R::Support.eval("`names<-`").call(value.r_interop, k)
146
+ params = R::Support.eval("c").call(params, na_named)
147
+ else
148
+ params = R::Support.eval("`[[<-`").
149
+ call(params, k, R::Support.parse_arg(value))
150
+ end
151
+ end
152
+ elsif (arg.is_a? NotAvailable)
153
+ params = R::Support.eval("c").call(params, arg.r_interop)
154
+ else
155
+ params = R::Support.eval("`[[<-`").
156
+ call(params, i+1, R::Support.parse_arg(arg))
157
+ end
158
+ end
159
+
160
+ params
161
+
162
+ end
163
+
164
+ #----------------------------------------------------------------------------------------
165
+ # Converts a Ruby symbol onto an R symbol. Converts '__' to '.' and 'rclass' to
166
+ # class
167
+ # @param symbol [Symbol] A Ruby symbol to convert to R
168
+ #----------------------------------------------------------------------------------------
169
+
170
+ def self.convert_symbol2r(symbol)
171
+ name = symbol.to_s
172
+ # convert '__' to '.'
173
+ name.gsub!(/__/,".")
174
+ # Method 'rclass' is a substitute for R method 'class'. Needed, as 'class' is also
175
+ # a Ruby method on an object
176
+ name.gsub!("rclass", "class")
177
+ name
178
+ end
179
+
180
+ #----------------------------------------------------------------------------------------
181
+ # Executes the given R function with the given arguments.
182
+ #----------------------------------------------------------------------------------------
183
+
184
+ def self.exec_function_i(function, *args)
185
+ pl = R::Support.parse2list(*args)
186
+ R::Support.eval("do.call").call(function, pl)
187
+ end
188
+
189
+ #----------------------------------------------------------------------------------------
190
+ # @param function [R function (Interop)] R function to execute
191
+ # @param internal [Boolean] true if returning to an internal object, i.e., does not
192
+ # wrap the return object in a Ruby object
193
+ # @args [Array] Array of arguments for the function
194
+ #----------------------------------------------------------------------------------------
195
+
196
+ def self.exec_function(function, *args)
197
+ # function has no arguments, call it directly
198
+ if (args.length == 0)
199
+ return R::Object.build(function.call) # if args.length == 0
200
+ end
201
+
202
+ pl = R::Support.parse2list(*args)
203
+ @@exec_from_ruby.call(R::Object.method(:build), function, pl)
204
+ # R::Object.build(R::Support.eval("do.call").call(function, pl))
205
+ end
206
+
207
+ #----------------------------------------------------------------------------------------
208
+ # @param function_name [String] Name of the R function to execute
209
+ # @param internal [Boolean] true if returning to an internal object, i.e., does not
210
+ # wrap the return object in a Ruby object
211
+ # @args [Array] Array of arguments for the function
212
+ #----------------------------------------------------------------------------------------
213
+
214
+ def self.exec_function_name(function_name, *args)
215
+ R::Support.exec_function(R::Support.eval(function_name), *args)
216
+ end
217
+
218
+ #----------------------------------------------------------------------------------------
219
+ # sets the R symbol <name> to the given value
220
+ # @param name [String] String representation of the R symbol that needs to be assigned
221
+ # @param args [Array] Array with one object to be set to the symbol
222
+ #----------------------------------------------------------------------------------------
223
+
224
+ def self.set_symbol(name, *args)
225
+ args << R::Support.eval("globalenv").call()
226
+ R::Support.exec_function_name("assign", name, *args)
227
+ end
228
+
229
+ #----------------------------------------------------------------------------------------
230
+ # Calls the R 'eval' function. This requires some special semantics
231
+ # R function 'eval' needs to be called in a special way, since it expects
232
+ # the second argument to be an environment. If the arguments are packed
233
+ # into a list, then there is no second argument and the function fails to
234
+ # use the second argument as environment
235
+ #----------------------------------------------------------------------------------------
236
+
237
+ def self.r_evaluate(*args)
238
+ r_args = args.map { |arg| R::Support.parse_arg(arg) }
239
+ R::Object.build(eval("eval").call(*r_args))
240
+ end
241
+
242
+ #----------------------------------------------------------------------------------------
243
+ # Process the missing method
244
+ # @param symbol [Symbol]
245
+ # @param internal [Boolean] true if the method will return to an internal method, i.e.,
246
+ # it should not wrap the return value inside an R::Object
247
+ # @param object [Ruby Object] the ruby object to which the method is applied, false if
248
+ # it is not applied to an object
249
+ #----------------------------------------------------------------------------------------
250
+
251
+ def self.process_missing(symbol, internal, *args)
252
+
253
+ name = R::Support.convert_symbol2r(symbol)
254
+
255
+ case name
256
+ # missing method has an '=' sign in it...
257
+ when ->(x) { x =~ /(.*)=$/ }
258
+ R::Support.set_symbol($1, *args)
259
+ # missing method is 'eval'... needs special treatment
260
+ when "eval"
261
+ R::Support.r_evaluate(*args)
262
+ else
263
+ function = R::Support.eval(name)
264
+ internal ? R::Support.exec_function_i(function, *args) :
265
+ R::Support.exec_function(function, *args)
266
+ end
267
+
268
+ end
269
+
270
+ #----------------------------------------------------------------------------------------
271
+ # Prints a foreign R interop pointer. Used for debug.
272
+ #----------------------------------------------------------------------------------------
273
+
274
+ def self.print_foreign(interop)
275
+ puts "===External value==="
276
+ R::Support.eval("print").call(interop)
277
+ puts "===end external value==="
278
+ end
279
+
280
+ class << self
281
+ alias :pf :print_foreign
282
+ end
283
+
284
+ #----------------------------------------------------------------------------------------
285
+ #
286
+ #----------------------------------------------------------------------------------------
287
+
288
+ end
289
+
290
+ end
291
+
292
+ require_relative 'rsupport_scope'