rinruby 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +1 -0
- data/History.txt +11 -0
- data/LICENSE.txt +646 -0
- data/Manifest.txt +9 -0
- data/README.txt +44 -624
- data/Rakefile +21 -0
- data/lib/rinruby.rb +159 -66
- data/spec/rinruby_spec.rb +105 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +17 -0
- metadata +104 -38
- metadata.gz.sig +0 -0
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# -*- ruby -*-
|
3
|
+
# -*- coding: utf-8 -*-
|
4
|
+
$:.unshift(File.dirname(__FILE__)+'/lib/')
|
5
|
+
require 'rubygems'
|
6
|
+
require 'hoe'
|
7
|
+
require './lib/rinruby'
|
8
|
+
|
9
|
+
Hoe.plugin :git
|
10
|
+
|
11
|
+
Hoe.spec 'rinruby' do
|
12
|
+
self.testlib=:rspec
|
13
|
+
self.version=RinRuby::VERSION
|
14
|
+
# self.rubyforge_name = 'rinruby' # if different than 'rinruby2'
|
15
|
+
self.developer('David Dahl', 'rinruby_AT_ddahl.org')
|
16
|
+
self.developer('Claudio Bustos', 'clbustos_AT_gmail.com')
|
17
|
+
self.url = "http://rinruby.ddahl.org/"
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
# vim: syntax=ruby
|
data/lib/rinruby.rb
CHANGED
@@ -56,16 +56,23 @@
|
|
56
56
|
#
|
57
57
|
#
|
58
58
|
#The files "java" and "readline" are used when available to add functionality.
|
59
|
-
|
59
|
+
require 'matrix'
|
60
60
|
class RinRuby
|
61
|
+
|
62
|
+
require 'socket'
|
61
63
|
|
62
|
-
|
64
|
+
|
65
|
+
VERSION = '1.2.0'
|
63
66
|
|
64
|
-
require 'socket'
|
65
67
|
|
66
68
|
attr_reader :interactive
|
67
69
|
attr_reader :readline
|
68
|
-
|
70
|
+
# Exception for closed engine
|
71
|
+
EngineClosed=Class.new(Exception)
|
72
|
+
# Parse error
|
73
|
+
ParseError=Class.new(Exception)
|
74
|
+
|
75
|
+
|
69
76
|
#RinRuby is invoked within a Ruby script (or the interactive "irb" prompt denoted >>) using:
|
70
77
|
#
|
71
78
|
# >> require "rinruby"
|
@@ -96,20 +103,20 @@ class RinRuby
|
|
96
103
|
while true
|
97
104
|
begin
|
98
105
|
@port_number = port_number + rand(port_width)
|
99
|
-
@server_socket = TCPServer::new("127.0.0.1"
|
106
|
+
@server_socket = TCPServer::new("127.0.0.1", @port_number)
|
100
107
|
break
|
101
108
|
rescue Errno::EADDRINUSE
|
102
|
-
sleep
|
109
|
+
sleep 0.5 if port_width == 1
|
103
110
|
end
|
104
111
|
end
|
105
112
|
@echo_enabled = echo
|
106
113
|
@echo_stderr = false
|
107
114
|
@interactive = interactive
|
108
115
|
@platform = case RUBY_PLATFORM
|
109
|
-
when /mswin
|
110
|
-
when /mingw
|
111
|
-
when /bccwin
|
112
|
-
when /cygwin
|
116
|
+
when /mswin/ then 'windows'
|
117
|
+
when /mingw/ then 'windows'
|
118
|
+
when /bccwin/ then 'windows'
|
119
|
+
when /cygwin/ then 'windows-cygwin'
|
113
120
|
when /java/
|
114
121
|
require 'java' #:nodoc:
|
115
122
|
if java.lang.System.getProperty("os.name") =~ /[Ww]indows/
|
@@ -137,10 +144,11 @@ class RinRuby
|
|
137
144
|
@engine = IO.popen(cmd,"w+")
|
138
145
|
@reader = @engine
|
139
146
|
@writer = @engine
|
147
|
+
raise "Engine closed" if @engine.closed?
|
140
148
|
@writer.puts <<-EOF
|
141
149
|
#{RinRuby_KeepTrying_Variable} <- TRUE
|
142
150
|
while ( #{RinRuby_KeepTrying_Variable} ) {
|
143
|
-
#{RinRuby_Socket} <- try(suppressWarnings(socketConnection("127.0.0.1"
|
151
|
+
#{RinRuby_Socket} <- try(suppressWarnings(socketConnection("127.0.0.1", #{@port_number}, blocking=TRUE, open="rb")),TRUE)
|
144
152
|
if ( inherits(#{RinRuby_Socket},"try-error") ) {
|
145
153
|
Sys.sleep(0.1)
|
146
154
|
} else {
|
@@ -149,6 +157,9 @@ class RinRuby
|
|
149
157
|
}
|
150
158
|
rm(#{RinRuby_KeepTrying_Variable})
|
151
159
|
EOF
|
160
|
+
r_rinruby_get_value
|
161
|
+
r_rinruby_pull
|
162
|
+
r_rinruby_parseable
|
152
163
|
@socket = @server_socket.accept
|
153
164
|
echo(nil,true) if @platform =~ /.*-java/ # Redirect error messages on the Java platform
|
154
165
|
end
|
@@ -156,13 +167,21 @@ class RinRuby
|
|
156
167
|
#The quit method will properly close the bridge between Ruby and R, freeing up system resources. This method does not need to be run when a Ruby script ends.
|
157
168
|
|
158
169
|
def quit
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
170
|
+
begin
|
171
|
+
@writer.puts "q(save='no')"
|
172
|
+
@socket.read()
|
173
|
+
#@socket.close
|
174
|
+
@engine.close
|
175
|
+
|
176
|
+
|
177
|
+
@server_socket.close
|
178
|
+
#@reader.close
|
179
|
+
#@writer.close
|
180
|
+
true
|
181
|
+
ensure
|
182
|
+
@engine.close unless @engine.closed?
|
183
|
+
@server_socket.close unless @server_socket.closed?
|
184
|
+
end
|
166
185
|
end
|
167
186
|
|
168
187
|
|
@@ -198,13 +217,14 @@ class RinRuby
|
|
198
217
|
#* echo_override: This argument allows one to set the echo behavior for this call only. The default for echo_override is nil, which does not override the current echo behavior.
|
199
218
|
|
200
219
|
def eval(string, echo_override=nil)
|
220
|
+
raise EngineClosed if @engine.closed?
|
201
221
|
echo_enabled = ( echo_override != nil ) ? echo_override : @echo_enabled
|
202
222
|
if complete?(string)
|
203
223
|
@writer.puts string
|
204
224
|
@writer.puts "warning('#{RinRuby_Stderr_Flag}',immediate.=TRUE)" if @echo_stderr
|
205
225
|
@writer.puts "print('#{RinRuby_Eval_Flag}')"
|
206
226
|
else
|
207
|
-
raise "Parse error"
|
227
|
+
raise ParseError, "Parse error on eval"
|
208
228
|
end
|
209
229
|
Signal.trap('INT') do
|
210
230
|
@writer.print ''
|
@@ -313,10 +333,11 @@ class RinRuby
|
|
313
333
|
def method_missing(symbol, *args)
|
314
334
|
name = symbol.id2name
|
315
335
|
if name =~ /(.*)=$/
|
316
|
-
raise "
|
336
|
+
raise ArgumentError, "You shouldn't assign nil" if args==[nil]
|
337
|
+
super if args.length != 1
|
317
338
|
assign($1,args[0])
|
318
339
|
else
|
319
|
-
|
340
|
+
super if args.length != 0
|
320
341
|
pull(name)
|
321
342
|
end
|
322
343
|
end
|
@@ -358,10 +379,11 @@ class RinRuby
|
|
358
379
|
#When assigning an array containing differing types of variables, RinRuby will follow R’s conversion conventions. An array that contains any Strings will result in a character vector in R. If the array does not contain any Strings, but it does contain a Float or a large integer (in absolute value), then the result will be a numeric vector of Doubles in R. If there are only integers that are suffciently small (in absolute value), then the result will be a numeric vector of integers in R.
|
359
380
|
|
360
381
|
def assign(name, value)
|
382
|
+
raise EngineClosed if @engine.closed?
|
361
383
|
if assignable?(name)
|
362
384
|
assign_engine(name,value)
|
363
385
|
else
|
364
|
-
raise "Parse error"
|
386
|
+
raise ParseError, "Parse error"
|
365
387
|
end
|
366
388
|
end
|
367
389
|
|
@@ -419,6 +441,7 @@ class RinRuby
|
|
419
441
|
# >> puts R.pull("test")
|
420
442
|
|
421
443
|
def pull(string, singletons=false)
|
444
|
+
raise EngineClosed if @engine.closed?
|
422
445
|
if complete?(string)
|
423
446
|
result = pull_engine(string)
|
424
447
|
if ( ! singletons ) && ( result.length == 1 ) && ( result.class != String )
|
@@ -426,7 +449,7 @@ class RinRuby
|
|
426
449
|
end
|
427
450
|
result
|
428
451
|
else
|
429
|
-
raise "Parse error"
|
452
|
+
raise ParseError, "Parse error"
|
430
453
|
end
|
431
454
|
end
|
432
455
|
|
@@ -466,6 +489,8 @@ class RinRuby
|
|
466
489
|
RinRuby_Type_Integer = 1
|
467
490
|
RinRuby_Type_String = 2
|
468
491
|
RinRuby_Type_String_Array = 3
|
492
|
+
RinRuby_Type_Matrix = 4
|
493
|
+
|
469
494
|
RinRuby_KeepTrying_Variable = ".RINRUBY.KEEPTRYING.VARIABLE"
|
470
495
|
RinRuby_Length_Variable = ".RINRUBY.PULL.LENGTH.VARIABLE"
|
471
496
|
RinRuby_Type_Variable = ".RINRUBY.PULL.TYPE.VARIABLE"
|
@@ -481,7 +506,77 @@ class RinRuby
|
|
481
506
|
RinRuby_Max_R_Integer = 2**31-1
|
482
507
|
RinRuby_Min_R_Integer = -2**31+1
|
483
508
|
#:startdoc:
|
484
|
-
|
509
|
+
|
510
|
+
|
511
|
+
def r_rinruby_parseable
|
512
|
+
@writer.puts <<-EOF
|
513
|
+
rinruby_parseable<-function(var) {
|
514
|
+
result=try(parse(text=var),TRUE)
|
515
|
+
if(inherits(result, "try-error")) {
|
516
|
+
writeBin(as.integer(-1),#{RinRuby_Socket}, endian="big")
|
517
|
+
} else {
|
518
|
+
writeBin(as.integer(1),#{RinRuby_Socket}, endian="big")
|
519
|
+
}
|
520
|
+
}
|
521
|
+
EOF
|
522
|
+
end
|
523
|
+
# Create function on ruby to get values
|
524
|
+
def r_rinruby_get_value
|
525
|
+
@writer.puts <<-EOF
|
526
|
+
rinruby_get_value <-function() {
|
527
|
+
value <- NULL
|
528
|
+
type <- readBin(#{RinRuby_Socket}, integer(), 1, endian="big")
|
529
|
+
length <- readBin(#{RinRuby_Socket},integer(),1,endian="big")
|
530
|
+
if ( type == #{RinRuby_Type_Double} ) {
|
531
|
+
value <- readBin(#{RinRuby_Socket},numeric(), length,endian="big")
|
532
|
+
} else if ( type == #{RinRuby_Type_Integer} ) {
|
533
|
+
value <- readBin(#{RinRuby_Socket},integer(), length, endian="big")
|
534
|
+
} else if ( type == #{RinRuby_Type_String} ) {
|
535
|
+
value <- readBin(#{RinRuby_Socket},character(),1,endian="big")
|
536
|
+
} else {
|
537
|
+
value <-NULL
|
538
|
+
}
|
539
|
+
value
|
540
|
+
}
|
541
|
+
EOF
|
542
|
+
end
|
543
|
+
|
544
|
+
def r_rinruby_pull
|
545
|
+
@writer.puts <<-EOF
|
546
|
+
rinruby_pull <-function(var)
|
547
|
+
{
|
548
|
+
if ( inherits(var ,"try-error") ) {
|
549
|
+
writeBin(as.integer(#{RinRuby_Type_NotFound}),#{RinRuby_Socket},endian="big")
|
550
|
+
} else {
|
551
|
+
if (is.matrix(var)) {
|
552
|
+
writeBin(as.integer(#{RinRuby_Type_Matrix}),#{RinRuby_Socket},endian="big")
|
553
|
+
writeBin(as.integer(dim(var)[1]),#{RinRuby_Socket},endian="big")
|
554
|
+
writeBin(as.integer(dim(var)[2]),#{RinRuby_Socket},endian="big")
|
555
|
+
|
556
|
+
} else if ( is.double(var) ) {
|
557
|
+
writeBin(as.integer(#{RinRuby_Type_Double}),#{RinRuby_Socket},endian="big")
|
558
|
+
writeBin(as.integer(length(var)),#{RinRuby_Socket},endian="big")
|
559
|
+
writeBin(var,#{RinRuby_Socket},endian="big")
|
560
|
+
} else if ( is.integer(var) ) {
|
561
|
+
writeBin(as.integer(#{RinRuby_Type_Integer}),#{RinRuby_Socket},endian="big")
|
562
|
+
writeBin(as.integer(length(var)),#{RinRuby_Socket},endian="big")
|
563
|
+
writeBin(var,#{RinRuby_Socket},endian="big")
|
564
|
+
} else if ( is.character(var) && ( length(var) == 1 ) ) {
|
565
|
+
writeBin(as.integer(#{RinRuby_Type_String}),#{RinRuby_Socket},endian="big")
|
566
|
+
writeBin(as.integer(nchar(var)),#{RinRuby_Socket},endian="big")
|
567
|
+
writeBin(var,#{RinRuby_Socket},endian="big")
|
568
|
+
} else if ( is.character(var) && ( length(var) > 1 ) ) {
|
569
|
+
writeBin(as.integer(#{RinRuby_Type_String_Array}),#{RinRuby_Socket},endian="big")
|
570
|
+
writeBin(as.integer(length(var)),#{RinRuby_Socket},endian="big")
|
571
|
+
} else {
|
572
|
+
writeBin(as.integer(#{RinRuby_Type_Unknown}),#{RinRuby_Socket},endian="big")
|
573
|
+
}
|
574
|
+
}
|
575
|
+
}
|
576
|
+
EOF
|
577
|
+
|
578
|
+
|
579
|
+
end
|
485
580
|
def to_signed_int(y)
|
486
581
|
if y.kind_of?(Integer)
|
487
582
|
( y > RinRuby_Half_Max_Unsigned_Integer ) ? -(RinRuby_Max_Unsigned_Integer-y) : ( y == RinRuby_NA_R_Integer ? nil : y )
|
@@ -492,6 +587,13 @@ class RinRuby
|
|
492
587
|
|
493
588
|
def assign_engine(name, value)
|
494
589
|
original_value = value
|
590
|
+
# Special assign for matrixes
|
591
|
+
if value.kind_of?(::Matrix)
|
592
|
+
values=value.row_size.times.collect {|i| value.column_size.times.collect {|j| value[i,j]}}.flatten
|
593
|
+
eval "#{name}=matrix(c(#{values.join(',')}), #{value.row_size}, #{value.column_size}, TRUE)"
|
594
|
+
return original_value
|
595
|
+
end
|
596
|
+
|
495
597
|
if value.kind_of?(String)
|
496
598
|
type = RinRuby_Type_String
|
497
599
|
length = 1
|
@@ -536,18 +638,8 @@ class RinRuby
|
|
536
638
|
else
|
537
639
|
raise "Unsupported data type on Ruby's end"
|
538
640
|
end
|
539
|
-
@writer.puts
|
540
|
-
|
541
|
-
#{RinRuby_Length_Variable} <- readBin(#{RinRuby_Socket},integer(),1,endian="big")
|
542
|
-
if ( #{RinRuby_Type_Variable} == #{RinRuby_Type_Double} ) {
|
543
|
-
#{name} <- readBin(#{RinRuby_Socket},numeric(),#{RinRuby_Length_Variable},endian="big")
|
544
|
-
} else if ( #{RinRuby_Type_Variable} == #{RinRuby_Type_Integer} ) {
|
545
|
-
#{name} <- readBin(#{RinRuby_Socket},integer(),#{RinRuby_Length_Variable},endian="big")
|
546
|
-
} else if ( #{RinRuby_Type_Variable} == #{RinRuby_Type_String} ) {
|
547
|
-
#{name} <- readBin(#{RinRuby_Socket},character(),1,endian="big")
|
548
|
-
} else { }
|
549
|
-
rm(#{RinRuby_Type_Variable},#{RinRuby_Length_Variable})
|
550
|
-
EOF
|
641
|
+
@writer.puts "#{name} <- rinruby_get_value()"
|
642
|
+
|
551
643
|
@socket.write([type,length].pack('NN'))
|
552
644
|
if ( type == RinRuby_Type_String )
|
553
645
|
@socket.write(value)
|
@@ -560,31 +652,9 @@ class RinRuby
|
|
560
652
|
|
561
653
|
def pull_engine(string)
|
562
654
|
@writer.puts <<-EOF
|
563
|
-
|
564
|
-
if ( inherits(#{RinRuby_Variable},"try-error") ) {
|
565
|
-
writeBin(as.integer(#{RinRuby_Type_NotFound}),#{RinRuby_Socket},endian="big")
|
566
|
-
} else {
|
567
|
-
if ( is.double(#{RinRuby_Variable}) ) {
|
568
|
-
writeBin(as.integer(#{RinRuby_Type_Double}),#{RinRuby_Socket},endian="big")
|
569
|
-
writeBin(as.integer(length(#{RinRuby_Variable})),#{RinRuby_Socket},endian="big")
|
570
|
-
writeBin(#{RinRuby_Variable},#{RinRuby_Socket},endian="big")
|
571
|
-
} else if ( is.integer(#{RinRuby_Variable}) ) {
|
572
|
-
writeBin(as.integer(#{RinRuby_Type_Integer}),#{RinRuby_Socket},endian="big")
|
573
|
-
writeBin(as.integer(length(#{RinRuby_Variable})),#{RinRuby_Socket},endian="big")
|
574
|
-
writeBin(#{RinRuby_Variable},#{RinRuby_Socket},endian="big")
|
575
|
-
} else if ( is.character(#{RinRuby_Variable}) && ( length(#{RinRuby_Variable}) == 1 ) ) {
|
576
|
-
writeBin(as.integer(#{RinRuby_Type_String}),#{RinRuby_Socket},endian="big")
|
577
|
-
writeBin(as.integer(nchar(#{RinRuby_Variable})),#{RinRuby_Socket},endian="big")
|
578
|
-
writeBin(#{RinRuby_Variable},#{RinRuby_Socket},endian="big")
|
579
|
-
} else if ( is.character(#{RinRuby_Variable}) && ( length(#{RinRuby_Variable}) > 1 ) ) {
|
580
|
-
writeBin(as.integer(#{RinRuby_Type_String_Array}),#{RinRuby_Socket},endian="big")
|
581
|
-
writeBin(as.integer(length(#{RinRuby_Variable})),#{RinRuby_Socket},endian="big")
|
582
|
-
} else {
|
583
|
-
writeBin(as.integer(#{RinRuby_Type_Unknown}),#{RinRuby_Socket},endian="big")
|
584
|
-
}
|
585
|
-
}
|
586
|
-
rm(#{RinRuby_Variable})
|
655
|
+
rinruby_pull(try(#{string}))
|
587
656
|
EOF
|
657
|
+
|
588
658
|
buffer = ""
|
589
659
|
@socket.read(4,buffer)
|
590
660
|
type = to_signed_int(buffer.unpack('N')[0].to_i)
|
@@ -596,6 +666,7 @@ class RinRuby
|
|
596
666
|
end
|
597
667
|
@socket.read(4,buffer)
|
598
668
|
length = to_signed_int(buffer.unpack('N')[0].to_i)
|
669
|
+
|
599
670
|
if ( type == RinRuby_Type_Double )
|
600
671
|
@socket.read(8*length,buffer)
|
601
672
|
result = buffer.unpack('G'*length)
|
@@ -612,6 +683,18 @@ class RinRuby
|
|
612
683
|
for index in 0...length
|
613
684
|
result[index] = pull "#{string}[#{index+1}]"
|
614
685
|
end
|
686
|
+
elsif (type == RinRuby_Type_Matrix)
|
687
|
+
rows=length
|
688
|
+
@socket.read(4,buffer)
|
689
|
+
cols = to_signed_int(buffer.unpack('N')[0].to_i)
|
690
|
+
elements=pull "as.vector(#{string})"
|
691
|
+
index=0
|
692
|
+
result=Matrix.rows(rows.times.collect {|i|
|
693
|
+
cols.times.collect {|j|
|
694
|
+
elements[(j*rows)+i]
|
695
|
+
}
|
696
|
+
})
|
697
|
+
def result.length; 2;end
|
615
698
|
else
|
616
699
|
raise "Unsupported data type on Ruby's end"
|
617
700
|
end
|
@@ -619,22 +702,32 @@ class RinRuby
|
|
619
702
|
end
|
620
703
|
|
621
704
|
def complete?(string)
|
622
|
-
assign_engine(RinRuby_Parse_String,string)
|
705
|
+
assign_engine(RinRuby_Parse_String, string)
|
706
|
+
@writer.puts "rinruby_parseable(#{RinRuby_Parse_String})"
|
707
|
+
buffer=""
|
708
|
+
@socket.read(4,buffer)
|
709
|
+
@writer.puts "rm(#{RinRuby_Parse_String})"
|
710
|
+
result = to_signed_int(buffer.unpack('N')[0].to_i)
|
711
|
+
return result==-1 ? false : true
|
712
|
+
|
713
|
+
=begin
|
714
|
+
|
623
715
|
result = pull_engine("unlist(lapply(c('.*','^Error in parse.*','^Error in parse.*unexpected end of input.*'),
|
624
716
|
grep,try({parse(text=#{RinRuby_Parse_String}); 1}, silent=TRUE)))")
|
625
|
-
|
717
|
+
|
626
718
|
return true if result.length == 1
|
627
719
|
return false if result.length == 3
|
628
|
-
raise "Parse error"
|
720
|
+
raise ParseError, "Parse error"
|
721
|
+
=end
|
629
722
|
end
|
630
|
-
|
723
|
+
public :complete?
|
631
724
|
def assignable?(string)
|
632
|
-
raise "Parse error" if ! complete?(string)
|
725
|
+
raise ParseError, "Parse error" if ! complete?(string)
|
633
726
|
assign_engine(RinRuby_Parse_String,string)
|
634
727
|
result = pull_engine("as.integer(ifelse(inherits(try({eval(parse(text=paste(#{RinRuby_Parse_String},'<- 1')))}, silent=TRUE),'try-error'),1,0))")
|
635
728
|
@writer.puts "rm(#{RinRuby_Parse_String})"
|
636
729
|
return true if result == [0]
|
637
|
-
raise "Parse error"
|
730
|
+
raise ParseError, "Parse error"
|
638
731
|
end
|
639
732
|
|
640
733
|
def find_R_on_windows(cygwin)
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe RinRuby do
|
4
|
+
before do
|
5
|
+
R.echo(false)
|
6
|
+
end
|
7
|
+
subject {R}
|
8
|
+
context "basic methods" do
|
9
|
+
it {should respond_to :eval}
|
10
|
+
it {should respond_to :quit}
|
11
|
+
it {should respond_to :assign}
|
12
|
+
it {should respond_to :pull}
|
13
|
+
it {should respond_to :quit}
|
14
|
+
it {should respond_to :echo}
|
15
|
+
it "return correct values for complete?" do
|
16
|
+
R.eval("x<-1").should be_true
|
17
|
+
end
|
18
|
+
it "return false for complete? for incorrect expressions" do
|
19
|
+
R.complete?("x<-").should be_false
|
20
|
+
end
|
21
|
+
it "correct eval should return true" do
|
22
|
+
R.complete?("x<-1").should be_true
|
23
|
+
end
|
24
|
+
it "incorrect eval should raise an ParseError" do
|
25
|
+
lambda {R.eval("x<-")}.should raise_error(RinRuby::ParseError)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
context "on assing" do
|
29
|
+
it "should assign correctly" do
|
30
|
+
x=rand
|
31
|
+
R.assign("x",x)
|
32
|
+
R.pull("x").should==x
|
33
|
+
end
|
34
|
+
it "should be the same using assign than R#= methods" do
|
35
|
+
x=rand
|
36
|
+
R.assign("x1",x)
|
37
|
+
R.x2=x
|
38
|
+
R.pull("x1").should==x
|
39
|
+
R.pull("x2").should==x
|
40
|
+
end
|
41
|
+
it "should raise an ArgumentError error on setter with 0 parameters" do
|
42
|
+
lambda {R.unknown_method=() }.should raise_error(ArgumentError)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
context "on pull" do
|
47
|
+
it "should be the same using pull than R# methods" do
|
48
|
+
x=rand
|
49
|
+
R.x=x
|
50
|
+
R.pull("x").should==x
|
51
|
+
R.x.should==x
|
52
|
+
end
|
53
|
+
it "should raise an NoMethod error on getter with 1 or more parameters" do
|
54
|
+
lambda {R.unknown_method(1) }.should raise_error(NoMethodError)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should pull a String" do
|
58
|
+
R.eval("x<-'Value'")
|
59
|
+
R.pull('x').should=='Value'
|
60
|
+
end
|
61
|
+
it "should pull an Integer" do
|
62
|
+
R.eval("x<-1")
|
63
|
+
R.pull('x').should==1
|
64
|
+
end
|
65
|
+
it "should pull a Float" do
|
66
|
+
R.eval("x<-1.5")
|
67
|
+
R.pull('x').should==1.5
|
68
|
+
end
|
69
|
+
it "should pull an Array of Numeric" do
|
70
|
+
R.eval("x<-c(1,2.5,3)")
|
71
|
+
R.pull('x').should==[1,2.5,3]
|
72
|
+
end
|
73
|
+
it "should pull an Array of strings" do
|
74
|
+
R.eval("x<-c('a','b')")
|
75
|
+
R.pull('x').should==['a','b']
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should push a Matrix" do
|
79
|
+
matrix=Matrix[[rand,rand,rand],[rand,rand,rand]]
|
80
|
+
lambda {R.assign('x',matrix)}.should_not raise_error
|
81
|
+
rx=R.x
|
82
|
+
matrix.row_size.times {|i|
|
83
|
+
matrix.column_size.times {|j|
|
84
|
+
matrix[i,j].should be_close(rx[i,j],1e-10)
|
85
|
+
}
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
context "on quit" do
|
92
|
+
before(:each) do
|
93
|
+
@r=RinRuby.new(false)
|
94
|
+
end
|
95
|
+
it "return true" do
|
96
|
+
@r.quit.should be_true
|
97
|
+
end
|
98
|
+
it "returns an error if used again" do
|
99
|
+
@r.quit
|
100
|
+
lambda {@r.eval("x=1")}.should raise_error(RinRuby::EngineClosed)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
end
|