alexgutteridge-rsruby 0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/Converters.h ADDED
@@ -0,0 +1,77 @@
1
+ /*
2
+ * == Author
3
+ * Alex Gutteridge
4
+ *
5
+ * == Copyright
6
+ *Copyright (C) 2006 Alex Gutteridge
7
+ *
8
+ * The Original Code is the RPy python module.
9
+ *
10
+ * The Initial Developer of the Original Code is Walter Moreira.
11
+ * Portions created by the Initial Developer are Copyright (C) 2002
12
+ * the Initial Developer. All Rights Reserved.
13
+ *
14
+ * Contributor(s):
15
+ * Gregory R. Warnes <greg@warnes.net> (RPy Maintainer)
16
+ *
17
+ *This library is free software; you can redistribute it and/or
18
+ *modify it under the terms of the GNU Lesser General Public
19
+ *License as published by the Free Software Foundation; either
20
+ *version 2.1 of the License, or (at your option) any later version.
21
+ *
22
+ *This library is distributed in the hope that it will be useful,
23
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25
+ *Lesser General Public License for more details.
26
+ *
27
+ *You should have received a copy of the GNU Lesser General Public
28
+ *License along with this library; if not, write to the Free Software
29
+ *Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30
+ */
31
+
32
+ #ifndef R_RUBY_CONVERTERS_H
33
+ #define R_RUBY_CONVERTERS_H
34
+
35
+ #include "rsruby.h"
36
+
37
+ //Converters for Ruby to R
38
+ SEXP ruby_to_R(VALUE val);
39
+
40
+ SEXP array_to_R(VALUE obj);
41
+ SEXP hash_to_R(VALUE obj);
42
+ int type_to_int(VALUE obj);
43
+
44
+ //Converters for R to Ruby
45
+ VALUE to_ruby_with_mode(SEXP robj, int mode);
46
+
47
+ int to_ruby_basic(SEXP robj, VALUE *obj);
48
+ int to_ruby_vector(SEXP robj, VALUE *obj, int mode);
49
+ int to_ruby_proc(SEXP robj, VALUE *obj);
50
+ int to_ruby_class(SEXP robj, VALUE *obj);
51
+ int from_proc_table(SEXP robj, VALUE *fun);
52
+ VALUE from_class_table(SEXP robj);
53
+
54
+ VALUE call_proc(VALUE data);
55
+ VALUE reset_mode(VALUE mode);
56
+
57
+ VALUE to_ruby_hash(VALUE obj, SEXP names);
58
+ VALUE to_ruby_array(VALUE obj, int *dims, int l);
59
+
60
+ VALUE ltranspose(VALUE list, int *dims, int *strides,
61
+ int pos, int shift, int len);
62
+
63
+ //Macros for quick checks
64
+ #define Robj_Check(v) (rb_obj_is_instance_of(v,rb_const_get(rb_cObject,rb_intern("RObj"))))
65
+ #define RubyComplex_Check(v) (rb_obj_is_instance_of(v,rb_const_get(rb_cObject,rb_intern("Complex"))))
66
+
67
+ /* These are auxiliaries for a state machine for converting Python
68
+ list to the coarsest R vector type */
69
+ #define ANY_T 0
70
+ #define BOOL_T 1
71
+ #define INT_T 2
72
+ #define FLOAT_T 3
73
+ #define COMPLEX_T 4
74
+ #define STRING_T 5
75
+ #define ROBJ_T 6
76
+
77
+ #endif
data/ext/R_eval.c ADDED
@@ -0,0 +1,144 @@
1
+ /*
2
+ * == Author
3
+ * Alex Gutteridge
4
+ *
5
+ * == Copyright
6
+ *Copyright (C) 2006 Alex Gutteridge
7
+ *
8
+ * The Original Code is the RPy python module.
9
+ *
10
+ * The Initial Developer of the Original Code is Walter Moreira.
11
+ * Portions created by the Initial Developer are Copyright (C) 2002
12
+ * the Initial Developer. All Rights Reserved.
13
+ *
14
+ * Contributor(s):
15
+ * Gregory R. Warnes <greg@warnes.net> (RPy Maintainer)
16
+ *
17
+ *This library is free software; you can redistribute it and/or
18
+ *modify it under the terms of the GNU Lesser General Public
19
+ *License as published by the Free Software Foundation; either
20
+ *version 2.1 of the License, or (at your option) any later version.
21
+ *
22
+ *This library is distributed in the hope that it will be useful,
23
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25
+ *Lesser General Public License for more details.
26
+ *
27
+ *You should have received a copy of the GNU Lesser General Public
28
+ *License along with this library; if not, write to the Free Software
29
+ *Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30
+ */
31
+
32
+ #include <rsruby.h>
33
+ #include <R_eval.h>
34
+
35
+ int interrupted = 0;
36
+
37
+ /* Abort the current R computation due to a SIGINT */
38
+ void interrupt_R(int signum)
39
+ {
40
+ interrupted = 1;
41
+ error("Interrupted");
42
+ }
43
+
44
+
45
+ /* Evaluate a SEXP. It must be constructed by hand. It raises a Ruby
46
+ exception if an error ocurred in the evaluation */
47
+ SEXP do_eval_expr(SEXP e) {
48
+ SEXP res;
49
+ VALUE rb_eRException;
50
+ int error = 0;
51
+
52
+ signal(SIGINT, interrupt_R);
53
+ interrupted = 0;
54
+
55
+ res = R_tryEval(e, R_GlobalEnv, &error);
56
+
57
+ if (error) {
58
+ if (interrupted) {
59
+ rb_raise(rb_eInterrupt,"RSRuby interrupted");
60
+ }
61
+ else {
62
+ rb_eRException = rb_const_get(rb_cObject,
63
+ rb_intern("RException"));
64
+ rb_raise(rb_eRException, get_last_error_msg());
65
+ return NULL;
66
+ }
67
+ }
68
+
69
+ return res;
70
+
71
+ }
72
+
73
+ /* Evaluate a function given by a name (without arguments) */
74
+ SEXP do_eval_fun(char *name) {
75
+ SEXP exp, fun, res;
76
+
77
+ fun = get_fun_from_name(name);
78
+ if (!fun)
79
+ return NULL;
80
+
81
+ PROTECT(fun);
82
+ PROTECT(exp = allocVector(LANGSXP, 1));
83
+ SETCAR(exp, fun);
84
+
85
+ PROTECT(res = do_eval_expr(exp));
86
+ UNPROTECT(3);
87
+ return res;
88
+ }
89
+
90
+ /*
91
+ * Get an R **function** object by its name. When not found, an exception is
92
+ * raised. The checking of the length of the identifier is needed to
93
+ * avoid R raising an error.
94
+ */
95
+ SEXP get_fun_from_name(char *ident) {
96
+ SEXP obj;
97
+
98
+ /* For R not to throw an error, we must check the identifier is
99
+ neither null nor greater than MAXIDSIZE */
100
+ if (!*ident) {
101
+ rb_raise(rb_eRuntimeError, "Attempt to use zero-length variable name");
102
+ return NULL;
103
+ }
104
+ if (strlen(ident) > MAXIDSIZE) {
105
+ rb_raise(rb_eRuntimeError, "symbol print-name too long");
106
+ return NULL;
107
+ }
108
+
109
+ #if R_VERSION < 0x20000
110
+ obj = Rf_findVar(Rf_install(ident), R_GlobalEnv);
111
+ #else
112
+ /*
113
+ * For R-2.0.0 and later, it is necessary to use findFun to get
114
+ * functions. Unfortunately, calling findFun on an undefined name
115
+ * causes a segfault!
116
+ *
117
+ * Solution:
118
+ *
119
+ * 1) Call findVar on the name
120
+ *
121
+ * 2) If something has the name, call findFun
122
+ *
123
+ * 3) Raise an error if either step 1 or 2 fails.
124
+ */
125
+ obj = Rf_findVar(Rf_install(ident), R_GlobalEnv);
126
+
127
+ if (obj != R_UnboundValue)
128
+ obj = Rf_findFun(Rf_install(ident), R_GlobalEnv);
129
+ #endif
130
+
131
+ if (obj == R_UnboundValue) {
132
+ rb_raise(rb_eNoMethodError, "R Function \"%s\" not found", ident);
133
+ return NULL;
134
+ }
135
+ return obj;
136
+ }
137
+
138
+ /* Obtain the text of the last R error message */
139
+ char *get_last_error_msg() {
140
+ SEXP msg;
141
+
142
+ msg = do_eval_fun("geterrmessage");
143
+ return CHARACTER_VALUE(msg);
144
+ }
data/ext/R_eval.h ADDED
@@ -0,0 +1,40 @@
1
+ /*
2
+ * == Author
3
+ * Alex Gutteridge
4
+ *
5
+ * == Copyright
6
+ *Copyright (C) 2006 Alex Gutteridge
7
+ *
8
+ * The Original Code is the RPy python module.
9
+ *
10
+ * The Initial Developer of the Original Code is Walter Moreira.
11
+ * Portions created by the Initial Developer are Copyright (C) 2002
12
+ * the Initial Developer. All Rights Reserved.
13
+ *
14
+ * Contributor(s):
15
+ * Gregory R. Warnes <greg@warnes.net> (RPy Maintainer)
16
+ *
17
+ *This library is free software; you can redistribute it and/or
18
+ *modify it under the terms of the GNU Lesser General Public
19
+ *License as published by the Free Software Foundation; either
20
+ *version 2.1 of the License, or (at your option) any later version.
21
+ *
22
+ *This library is distributed in the hope that it will be useful,
23
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25
+ *Lesser General Public License for more details.
26
+ *
27
+ *You should have received a copy of the GNU Lesser General Public
28
+ *License along with this library; if not, write to the Free Software
29
+ *Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30
+ */
31
+
32
+ /* R Evaluation */
33
+ SEXP do_eval_expr(SEXP e);
34
+ SEXP do_eval_fun(char *);
35
+ SEXP get_fun_from_name(char *);
36
+
37
+ /* Interrupt the R interpreter */
38
+ void interrupt_R(int);
39
+
40
+ char *get_last_error_msg(void);
data/ext/extconf.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('R')
4
+ unless have_library("R")
5
+ $stderr.puts "\nERROR: Cannot find the R library, aborting."
6
+ exit 1
7
+ end
8
+ unless have_header("R.h")
9
+ $stderr.puts "\nERROR: Cannot find the R header, aborting."
10
+ exit 1
11
+ end
12
+
13
+ create_makefile("rsruby_c")
data/ext/robj.c ADDED
@@ -0,0 +1,205 @@
1
+ /*
2
+ * == Author
3
+ * Alex Gutteridge
4
+ *
5
+ * == Copyright
6
+ *Copyright (C) 2006 Alex Gutteridge
7
+ *
8
+ * The Original Code is the RPy python module.
9
+ *
10
+ * The Initial Developer of the Original Code is Walter Moreira.
11
+ * Portions created by the Initial Developer are Copyright (C) 2002
12
+ * the Initial Developer. All Rights Reserved.
13
+ *
14
+ * Contributor(s):
15
+ * Gregory R. Warnes <greg@warnes.net> (RPy Maintainer)
16
+ *
17
+ *This library is free software; you can redistribute it and/or
18
+ *modify it under the terms of the GNU Lesser General Public
19
+ *License as published by the Free Software Foundation; either
20
+ *version 2.1 of the License, or (at your option) any later version.
21
+ *
22
+ *This library is distributed in the hope that it will be useful,
23
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25
+ *Lesser General Public License for more details.
26
+ *
27
+ *You should have received a copy of the GNU Lesser General Public
28
+ *License along with this library; if not, write to the Free Software
29
+ *Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30
+ */
31
+
32
+ #include "rsruby.h"
33
+
34
+ /* Methods for the 'Robj' type */
35
+
36
+ /* Explicitly call an R object with a list containing (name, value) *
37
+ * argument pairs. 'name' can be None or '' to provide unnamed
38
+ * arguments. This function is necessary when the *order* of named
39
+ * arguments needs to be preserved.
40
+ */
41
+
42
+ VALUE RObj_lcall(VALUE self, VALUE args){
43
+ SEXP exp, e, res;
44
+ SEXP r_obj;
45
+ int conv, default_mode;
46
+ VALUE obj;
47
+
48
+ //Ensure we have an array
49
+ args = rb_check_array_type(args);
50
+
51
+ // A SEXP with the function to call and the arguments
52
+ PROTECT(exp = allocVector(LANGSXP, (RARRAY(args)->len)+1));
53
+ e = exp;
54
+
55
+ Data_Get_Struct(self, struct SEXPREC, r_obj);
56
+
57
+ SETCAR(e, r_obj);
58
+ e = CDR(e);
59
+
60
+ // Add the arguments to the SEXP
61
+ if (!make_argl(args, &e)) {
62
+ UNPROTECT(1);
63
+ return Qnil;
64
+ }
65
+
66
+ // Evaluate
67
+ PROTECT(res = do_eval_expr(exp));
68
+ if (!res) {
69
+ UNPROTECT(2);
70
+ return Qnil;
71
+ }
72
+
73
+ default_mode = NUM2INT(rb_iv_get(RSRUBY,"@default_mode"));
74
+
75
+ // Convert
76
+ if (default_mode < 0){
77
+ conv = NUM2INT(rb_iv_get(self,"@conversion"));
78
+ } else {
79
+ conv = default_mode;
80
+ }
81
+
82
+ obj = to_ruby_with_mode(res, conv);
83
+
84
+ UNPROTECT(2);
85
+
86
+ return obj;
87
+ }
88
+
89
+
90
+ //lcall method that is safe to call during RSRuby initialisation
91
+ VALUE RObj_init_lcall(VALUE self, VALUE args){
92
+ SEXP exp, e, res;
93
+ SEXP r_obj;
94
+ VALUE obj;
95
+
96
+ //Ensure we have an array
97
+ args = rb_check_array_type(args);
98
+
99
+ // A SEXP with the function to call and the arguments
100
+ PROTECT(exp = allocVector(LANGSXP, (RARRAY(args)->len)+1));
101
+ e = exp;
102
+
103
+ Data_Get_Struct(self, struct SEXPREC, r_obj);
104
+
105
+ SETCAR(e, r_obj);
106
+ e = CDR(e);
107
+
108
+ // Add the arguments to the SEXP
109
+ if (!make_argl(args, &e)) {
110
+ UNPROTECT(1);
111
+ return Qnil;
112
+ }
113
+
114
+ // Evaluate
115
+ PROTECT(res = do_eval_expr(exp));
116
+ if (!res) {
117
+ UNPROTECT(2);
118
+ return Qnil;
119
+ }
120
+
121
+ obj = to_ruby_with_mode(res, BASIC_CONVERSION);
122
+
123
+ UNPROTECT(2);
124
+
125
+ return obj;
126
+ }
127
+
128
+ /* Convert a sequence of (name, value) pairs to arguments to an R
129
+ function call */
130
+ int
131
+ make_argl(VALUE args, SEXP *e)
132
+ {
133
+ SEXP rvalue;
134
+ int i;
135
+ VALUE pair, name, value;
136
+
137
+ //Ensure we have an array
138
+ args = rb_check_array_type(args);
139
+
140
+ for (i=0; i<RARRAY(args)->len; i++) {
141
+ pair = rb_ary_entry(args, i);
142
+ pair = rb_check_array_type(pair);
143
+ if(RARRAY(pair)->len != 2)
144
+ rb_raise(rb_eArgError,"Misformed argument in lcall\n");
145
+
146
+ /* Name must be a string. If it is empty string '' then no name*/
147
+ name = rb_ary_entry(pair, 0);
148
+ name = StringValue(name);
149
+ name = rb_funcall(rb_const_get(rb_cObject,
150
+ rb_intern("RSRuby")),
151
+ rb_intern("convert_method_name"),1,name);
152
+
153
+ /* Value can be anything. */
154
+ value = rb_ary_entry(pair, 1);
155
+ rvalue = ruby_to_R(value);
156
+
157
+ /* Add parameter value to call */
158
+ SETCAR(*e, rvalue);
159
+
160
+ /* Add name (if present) */
161
+ if (RSTRING(name)->len > 0)
162
+ {
163
+ SET_TAG(*e, Rf_install(RSTRING(name)->ptr));
164
+ }
165
+
166
+ /* Move index to new end of call */
167
+ *e = CDR(*e);
168
+ }
169
+ return 1;
170
+ }
171
+
172
+ VALUE RObj_to_ruby(VALUE self, VALUE args){
173
+
174
+ int conv;
175
+ VALUE obj;
176
+ SEXP robj;
177
+
178
+ args = rb_check_array_type(args);
179
+
180
+ if (RARRAY(args)->len > 1){
181
+ rb_raise(rb_eArgError,"Too many arguments in to_ruby\n");
182
+ }
183
+
184
+ if (RARRAY(args)->len == 0){
185
+ conv = NUM2INT(rb_iv_get(RSRUBY,"@default_mode"));
186
+ } else {
187
+ conv = NUM2INT(rb_ary_entry(args,0));
188
+ }
189
+
190
+ if (conv <= -2 || conv > TOP_MODE) {
191
+ rb_raise(rb_eArgError, "Wrong mode\n");
192
+ return Qnil;
193
+ }
194
+
195
+ if (conv < 0)
196
+ conv = TOP_MODE;
197
+
198
+ Data_Get_Struct(self, struct SEXPREC, robj);
199
+
200
+ obj = to_ruby_with_mode(robj, conv);
201
+ return obj;
202
+
203
+ }
204
+
205
+