rinruby 1.1.1 → 1.2.0
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.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
|