alexgutteridge-rsruby 0.5

Sign up to get free protection for your applications and to get access to all the features.
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
+