Skip to content

Commit d98eba5

Browse files
authored
Merge pull request #91 from sue445/rb_eval_string_protect
Add RbEvalStringProtect, RbAryNew, RbAryNewCapa, RbAryPush
2 parents 5e20e74 + a515fee commit d98eba5

File tree

7 files changed

+150
-3
lines changed

7 files changed

+150
-3
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,12 @@ ref. https://docs.ruby-lang.org/ja/latest/function/index.html
126126
* [ ] `rb_ary_delete`
127127
* [ ] `rb_ary_entry`
128128
* [ ] `rb_ary_includes`
129-
* [ ] `rb_ary_new`
130-
* [ ] `rb_ary_new2`
129+
* [x] `rb_ary_new`
130+
* [x] `rb_ary_new2`
131131
* [ ] `rb_ary_new3`
132+
* [x] `rb_ary_new_capa`
132133
* [ ] `rb_ary_pop`
133-
* [ ] `rb_ary_push`
134+
* [x] `rb_ary_push`
134135
* [ ] `rb_ary_shift`
135136
* [ ] `rb_ary_sort`
136137
* [ ] `rb_ary_store`

ruby-internal-eval.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ package ruby
55
*/
66
import "C"
77

8+
import (
9+
"unsafe"
10+
)
11+
812
// c.f. https://github.com/ruby/ruby/blob/master/include/ruby/internal/eval.h
913

1014
// RbFuncallv calls `rb_funcallv` in C
@@ -46,3 +50,19 @@ func RbEvalString(str string) VALUE {
4650

4751
return VALUE(C.rb_eval_string(char))
4852
}
53+
54+
// RbEvalStringProtect calls `rb_eval_string_protect` in C
55+
//
56+
// Original definition is following
57+
//
58+
// VALUE rb_eval_string_protect(const char *str, int *state)
59+
func RbEvalStringProtect(str string, state *Int) VALUE {
60+
char, clean := string2Char(str)
61+
defer clean()
62+
63+
var cState C.int
64+
ret := C.rb_eval_string_protect(char, (*C.int)(unsafe.Pointer(&cState)))
65+
*state = Int(cState)
66+
67+
return VALUE(ret)
68+
}

ruby-internal-intern-array.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package ruby
2+
3+
/*
4+
#include "ruby.h"
5+
*/
6+
import "C"
7+
8+
// c.f. https://github.com/ruby/ruby/blob/master/include/ruby/internal/intern/array.h
9+
10+
// RbAryNew calls `rb_ary_new` in C
11+
//
12+
// Original definition is following
13+
//
14+
// VALUE rb_ary_new(void)
15+
func RbAryNew() VALUE {
16+
return VALUE(C.rb_ary_new())
17+
}
18+
19+
// RbAryNewCapa calls `rb_ary_new_capa` in C
20+
//
21+
// Original definition is following
22+
//
23+
// VALUE rb_ary_new_capa(long capa)
24+
func RbAryNewCapa(capa int64) VALUE {
25+
return VALUE(C.rb_ary_new_capa(C.long(capa)))
26+
}
27+
28+
// RbAryNew2 is alias to [RbAryNewCapa]
29+
func RbAryNew2(capa int64) VALUE {
30+
return RbAryNewCapa(capa)
31+
}
32+
33+
// RbAryPush calls `rb_ary_push` in C
34+
//
35+
// Original definition is following
36+
//
37+
// VALUE rb_ary_push(VALUE ary, VALUE elem)
38+
func RbAryPush(ary VALUE, elem VALUE) VALUE {
39+
return VALUE(C.rb_ary_push(C.VALUE(ary), C.VALUE(elem)))
40+
}

testdata/dummy/ext/dummy/tests.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ void rb_dummy_tests_rb_const_set(VALUE self, VALUE name, VALUE val);
1818
VALUE rb_dummy_tests_rb_const_defined(VALUE self, VALUE name);
1919
VALUE rb_dummy_tests_rb_const_defined_at(VALUE self, VALUE name);
2020
VALUE rb_dummy_tests_rb_eval_string(VALUE self, VALUE str);
21+
VALUE rb_dummy_tests_rb_eval_string_protect(VALUE self, VALUE str);
22+
VALUE rb_dummy_tests_rb_ary_new(VALUE self);
23+
VALUE rb_dummy_tests_rb_ary_new_capa(VALUE self, VALUE capa);
24+
VALUE rb_dummy_tests_rb_ary_push(VALUE self, VALUE ary, VALUE elem);
2125
*/
2226
import "C"
2327

@@ -163,6 +167,41 @@ func rb_dummy_tests_rb_eval_string(_ C.VALUE, str C.VALUE) C.VALUE {
163167
return C.VALUE(ret)
164168
}
165169

170+
//export rb_dummy_tests_rb_eval_string_protect
171+
func rb_dummy_tests_rb_eval_string_protect(_ C.VALUE, str C.VALUE) C.VALUE {
172+
goStr := ruby.Value2String(ruby.VALUE(str))
173+
174+
var state ruby.Int
175+
ret := ruby.RbEvalStringProtect(goStr, &state)
176+
177+
slice := []ruby.VALUE{ret, ruby.INT2NUM(state)}
178+
ary := ruby.Slice2rbAry(slice)
179+
180+
return C.VALUE(ary)
181+
}
182+
183+
//export rb_dummy_tests_rb_ary_new
184+
func rb_dummy_tests_rb_ary_new(_ C.VALUE) C.VALUE {
185+
ret := ruby.RbAryNew()
186+
187+
return C.VALUE(ret)
188+
}
189+
190+
//export rb_dummy_tests_rb_ary_new_capa
191+
func rb_dummy_tests_rb_ary_new_capa(_ C.VALUE, capa C.VALUE) C.VALUE {
192+
longCapa := ruby.NUM2LONG(ruby.VALUE(capa))
193+
ret := ruby.RbAryNewCapa(int64(longCapa))
194+
195+
return C.VALUE(ret)
196+
}
197+
198+
//export rb_dummy_tests_rb_ary_push
199+
func rb_dummy_tests_rb_ary_push(_ C.VALUE, ary C.VALUE, elem C.VALUE) C.VALUE {
200+
ret := ruby.RbAryPush(ruby.VALUE(ary), ruby.VALUE(elem))
201+
202+
return C.VALUE(ret)
203+
}
204+
166205
// defineMethodsToDummyTests define methods in Dummy::Tests
167206
func defineMethodsToDummyTests(rb_mDummy ruby.VALUE) {
168207
rb_cTests := ruby.RbDefineClassUnder(rb_mDummy, "Tests", ruby.VALUE(C.rb_cObject))
@@ -183,4 +222,8 @@ func defineMethodsToDummyTests(rb_mDummy ruby.VALUE) {
183222
ruby.RbDefineSingletonMethod(rb_cTests, "rb_const_defined", C.rb_dummy_tests_rb_const_defined, 1)
184223
ruby.RbDefineSingletonMethod(rb_cTests, "rb_const_defined_at", C.rb_dummy_tests_rb_const_defined_at, 1)
185224
ruby.RbDefineSingletonMethod(rb_cTests, "rb_eval_string", C.rb_dummy_tests_rb_eval_string, 1)
225+
ruby.RbDefineSingletonMethod(rb_cTests, "rb_eval_string_protect", C.rb_dummy_tests_rb_eval_string_protect, 1)
226+
ruby.RbDefineSingletonMethod(rb_cTests, "rb_ary_new", C.rb_dummy_tests_rb_ary_new, 0)
227+
ruby.RbDefineSingletonMethod(rb_cTests, "rb_ary_new_capa", C.rb_dummy_tests_rb_ary_new_capa, 1)
228+
ruby.RbDefineSingletonMethod(rb_cTests, "rb_ary_push", C.rb_dummy_tests_rb_ary_push, 2)
186229
}

testdata/dummy/sig/dummy/tests.rbs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,9 @@ module Dummy
2525
def self.rb_const_defined: (string name) -> bool
2626
def self.rb_const_defined_at: (string name) -> bool
2727
def self.rb_eval_string: (string str) -> untyped
28+
def self.rb_eval_string_protect: (string str) -> [untyped, Integer]
29+
def self.rb_ary_new: () -> []
30+
def self.rb_ary_new_capa: (Integer capa) -> []
31+
def self.rb_ary_push: ([] ary, untyped elem) -> []
2832
end
2933
end

testdata/dummy/spec/dummy/tests_spec.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,32 @@
188188
expect(Dummy::Tests.rb_eval_string("1 + 2")).to eq 3
189189
end
190190
end
191+
192+
describe ".rb_eval_string_protect" do
193+
it "works" do
194+
ret, state = Dummy::Tests.rb_eval_string_protect("1 + 2")
195+
196+
expect(ret).to eq 3
197+
expect(state).to eq 0
198+
end
199+
end
200+
201+
describe ".rb_ary_new" do
202+
it "works" do
203+
expect(Dummy::Tests.rb_ary_new).to eq []
204+
end
205+
end
206+
207+
describe ".rb_ary_new_capa" do
208+
it "works" do
209+
expect(Dummy::Tests.rb_ary_new_capa(1)).to eq []
210+
end
211+
end
212+
213+
describe ".rb_ary_push" do
214+
it "works" do
215+
ret = Dummy::Tests.rb_ary_push([1], 2)
216+
expect(ret).to eq [1, 2]
217+
end
218+
end
191219
end

wrapper.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,14 @@ func Int2Bool(i Int) bool {
131131
func int2Bool(i C.int) bool {
132132
return i != 0
133133
}
134+
135+
// Slice2rbAry convert from Go slice to rb_ary
136+
func Slice2rbAry(slice []VALUE) VALUE {
137+
rbAry := RbAryNewCapa(int64(len(slice)))
138+
139+
for _, v := range slice {
140+
RbAryPush(rbAry, v)
141+
}
142+
143+
return rbAry
144+
}

0 commit comments

Comments
 (0)