rufus-lua 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +17 -0
- data/CREDITS.txt +7 -2
- data/LICENSE.txt +1 -1
- data/README.md +263 -0
- data/Rakefile +82 -0
- data/lib/rufus/lua.rb +4 -1
- data/lib/rufus/lua/error.rb +86 -0
- data/lib/rufus/lua/lib.rb +34 -14
- data/lib/rufus/lua/objects.rb +11 -12
- data/lib/rufus/lua/state.rb +74 -55
- data/lib/rufus/lua/utils.rb +3 -3
- data/lib/rufus/lua/version.rb +32 -0
- data/rufus-lua.gemspec +36 -0
- data/spec/coroutines_spec.rb +90 -0
- data/spec/eval_spec.rb +125 -0
- data/spec/functions_spec.rb +119 -0
- data/spec/gc_spec.rb +41 -0
- data/spec/lib_spec.rb +32 -0
- data/spec/rfunctions_spec.rb +282 -0
- data/spec/spec_base.rb +10 -0
- data/spec/state_spec.rb +106 -0
- data/spec/string_spec.rb +46 -0
- data/spec/tables_spec.rb +165 -0
- data/spec/utils_spec.rb +36 -0
- data/test/bm0.rb +41 -0
- data/test/bm_fiber.rb +78 -0
- data/test/bm_gc_stop.rb +43 -0
- data/test/gc0.rb +19 -0
- data/test/t.rb +19 -0
- metadata +105 -56
- data/README.rdoc +0 -210
data/lib/rufus/lua/utils.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2009, John Mettraux, Alain Hoang.
|
2
|
+
# Copyright (c) 2009-2014, John Mettraux, Alain Hoang.
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -39,7 +39,7 @@ module Rufus::Lua
|
|
39
39
|
# #
|
40
40
|
# # => '{ "a": "A", "b": 2 }'
|
41
41
|
#
|
42
|
-
def self.to_lua_s
|
42
|
+
def self.to_lua_s(o)
|
43
43
|
|
44
44
|
case o
|
45
45
|
|
@@ -62,7 +62,7 @@ module Rufus::Lua
|
|
62
62
|
# Turns a Ruby Array or Hash instance into a Lua parseable string
|
63
63
|
# representation.
|
64
64
|
#
|
65
|
-
def self.to_lua_table_s
|
65
|
+
def self.to_lua_table_s(o)
|
66
66
|
|
67
67
|
s = if o.is_a?(Array)
|
68
68
|
o.collect { |e| to_lua_s(e) }
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009-2014, John Mettraux, Alain Hoang.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
|
26
|
+
module Rufus
|
27
|
+
module Lua
|
28
|
+
|
29
|
+
VERSION = '1.1.1'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
data/rufus-lua.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
|
4
|
+
s.name = 'rufus-lua'
|
5
|
+
|
6
|
+
s.version = File.read(
|
7
|
+
File.expand_path('../lib/rufus/lua/version.rb', __FILE__)
|
8
|
+
).match(/ VERSION *= *['"]([^'"]+)/)[1]
|
9
|
+
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.authors = [ 'John Mettraux', 'Alain Hoang', 'Scott Persinger' ]
|
12
|
+
s.email = [ 'jmettraux@gmail.com' ]
|
13
|
+
s.homepage = 'https://github.com/jmettraux/rufus-lua'
|
14
|
+
s.rubyforge_project = 'rufus'
|
15
|
+
s.license = 'MIT'
|
16
|
+
s.summary = 'ruby-ffi based bridge from Ruby to Lua'
|
17
|
+
|
18
|
+
s.description = %{
|
19
|
+
ruby-ffi based bridge from Ruby to Lua
|
20
|
+
}.strip
|
21
|
+
|
22
|
+
#s.files = `git ls-files`.split("\n")
|
23
|
+
s.files = Dir[
|
24
|
+
'Rakefile',
|
25
|
+
'lib/**/*.rb', 'spec/**/*.rb', 'test/**/*.rb',
|
26
|
+
'*.gemspec', '*.txt', '*.rdoc', '*.md'
|
27
|
+
]
|
28
|
+
|
29
|
+
s.add_dependency 'ffi', '~> 1.9'
|
30
|
+
|
31
|
+
s.add_development_dependency 'rake'
|
32
|
+
s.add_development_dependency 'rspec', '>= 2.13.0'
|
33
|
+
|
34
|
+
s.require_path = 'lib'
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,90 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-lua
|
4
|
+
#
|
5
|
+
# Sat Mar 14 23:51:42 JST 2009
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'spec_base'
|
9
|
+
|
10
|
+
|
11
|
+
describe Rufus::Lua::State do
|
12
|
+
|
13
|
+
describe 'a Lua coroutine' do
|
14
|
+
|
15
|
+
before do
|
16
|
+
@s = Rufus::Lua::State.new
|
17
|
+
end
|
18
|
+
after do
|
19
|
+
@s.close
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'can be returned to Ruby' do
|
23
|
+
|
24
|
+
expect(@s.eval(
|
25
|
+
'return coroutine.create(function (x) end)'
|
26
|
+
).class).to eq(Rufus::Lua::Coroutine)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'has a status visible from Ruby' do
|
30
|
+
|
31
|
+
co = @s.eval(
|
32
|
+
'return coroutine.create(function (x) end)'
|
33
|
+
)
|
34
|
+
expect(co.status).to eq('suspended')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'can be resumed from Ruby' do
|
38
|
+
|
39
|
+
@s.eval(%{
|
40
|
+
co = coroutine.create(function (x)
|
41
|
+
while true do
|
42
|
+
coroutine.yield(x)
|
43
|
+
end
|
44
|
+
end)
|
45
|
+
})
|
46
|
+
expect(@s['co'].resume(7)).to eq [ true, 7.0 ]
|
47
|
+
expect(@s['co'].resume()).to eq [ true, 7.0 ]
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'can be resumed from Ruby (and is not averse to \0 bytes)' do
|
51
|
+
|
52
|
+
@s.eval(%{
|
53
|
+
co = coroutine.create(function (x)
|
54
|
+
while true do
|
55
|
+
coroutine.yield(x)
|
56
|
+
end
|
57
|
+
end)
|
58
|
+
})
|
59
|
+
s = [ 0, 64, 0, 0, 65, 0 ].pack('c*')
|
60
|
+
expect(@s['co'].resume(s)).to eq [ true, s ]
|
61
|
+
expect(@s['co'].resume()).to eq [ true, s ]
|
62
|
+
end
|
63
|
+
|
64
|
+
# compressed version of the spec proposed by Nathanael Jones
|
65
|
+
# in https://github.com/nathanaeljones/rufus-lua/commit/179184aS
|
66
|
+
#
|
67
|
+
# for https://github.com/jmettraux/rufus-lua/issues/19
|
68
|
+
#
|
69
|
+
it 'yields the right value' do
|
70
|
+
|
71
|
+
pending 'yield across callback no worky on Lua 5.1.x'
|
72
|
+
|
73
|
+
@s.function :host_function do
|
74
|
+
'success'
|
75
|
+
end
|
76
|
+
r = @s.eval(%{
|
77
|
+
function routine()
|
78
|
+
coroutine.yield(host_function())
|
79
|
+
--coroutine.yield("success") -- that works :-(
|
80
|
+
end
|
81
|
+
co = coroutine.create(routine)
|
82
|
+
a, b = coroutine.resume(co)
|
83
|
+
return { a, b }
|
84
|
+
}).to_ruby
|
85
|
+
|
86
|
+
expect(r).to eq([ true, 'success' ])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
data/spec/eval_spec.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-lua
|
4
|
+
#
|
5
|
+
# Wed Mar 11 17:09:17 JST 2009
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'spec_base'
|
9
|
+
|
10
|
+
|
11
|
+
describe Rufus::Lua::State do
|
12
|
+
|
13
|
+
before do
|
14
|
+
@s = Rufus::Lua::State.new
|
15
|
+
end
|
16
|
+
after do
|
17
|
+
@s.close
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#[]' do
|
21
|
+
|
22
|
+
it 'returns nil for an unknown value/binding' do
|
23
|
+
|
24
|
+
expect(@s['unknown']).to eq nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#eval' do
|
29
|
+
|
30
|
+
it 'evals true' do
|
31
|
+
|
32
|
+
@s.eval('a = true')
|
33
|
+
expect(@s['a']).to eq true
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'evals false' do
|
37
|
+
|
38
|
+
@s.eval('a = false')
|
39
|
+
expect(@s['a']).to eq false
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'evals strings' do
|
43
|
+
|
44
|
+
@s.eval('a = "black adder"')
|
45
|
+
expect(@s['a']).to eq 'black adder'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'evals additions' do
|
49
|
+
|
50
|
+
@s.eval('a = 1 + 1')
|
51
|
+
expect(@s['a']).to eq 2.0
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'evals nested lookups' do
|
55
|
+
|
56
|
+
@s.eval('a = { b = { c = 0 } }')
|
57
|
+
@s.eval('_ = a.b.c')
|
58
|
+
expect(@s['_']).to eq 0
|
59
|
+
end
|
60
|
+
|
61
|
+
#it 'returns the global environment' do
|
62
|
+
# @s['_G']).to eq {}
|
63
|
+
#end
|
64
|
+
|
65
|
+
it 'returns numbers' do
|
66
|
+
|
67
|
+
expect(@s.eval('return 7')).to eq 7.0
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'returns multiple values' do
|
71
|
+
|
72
|
+
expect(@s.eval('return 1, 2')).to eq [ 1.0, 2.0 ]
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'returns false' do
|
76
|
+
|
77
|
+
expect(@s.eval('return false')).to eq false
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'returns true' do
|
81
|
+
|
82
|
+
expect(@s.eval('return true')).to eq true
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'accepts a binding optional argument'
|
86
|
+
|
87
|
+
it 'accepts a filename and a lineno optional arguments' do
|
88
|
+
|
89
|
+
le = nil
|
90
|
+
begin
|
91
|
+
@s.eval('error(77)', nil, '/nada/virtual.lua', 63)
|
92
|
+
rescue Rufus::Lua::LuaError => le
|
93
|
+
end
|
94
|
+
|
95
|
+
expect(le.filename).to eq('/nada/virtual.lua')
|
96
|
+
expect(le.lineno).to eq(63)
|
97
|
+
|
98
|
+
expect(le.original_backtrace.first).to match(/\/lua\/state\.rb:/)
|
99
|
+
expect(le.backtrace.first).to eq('/nada/virtual.lua:63:')
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'and errors' do
|
103
|
+
|
104
|
+
it 'makes the file and line available' do
|
105
|
+
|
106
|
+
le = nil
|
107
|
+
begin
|
108
|
+
@s.eval('error(77)')
|
109
|
+
rescue Rufus::Lua::LuaError => le
|
110
|
+
end
|
111
|
+
|
112
|
+
expect(le.kind).to eq('eval:pcall')
|
113
|
+
expect(le.msg).to eq('[string "line"]:1: 77')
|
114
|
+
expect(le.errcode).to eq(2)
|
115
|
+
|
116
|
+
expect(le.filename).to eq(__FILE__)
|
117
|
+
expect(le.lineno).to eq(__LINE__ - 9)
|
118
|
+
|
119
|
+
expect(le.original_backtrace.first).to match(/\/lua\/state\.rb:/)
|
120
|
+
expect(le.backtrace.first).to match(/\/eval_spec\.rb:/)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
@@ -0,0 +1,119 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-lua
|
4
|
+
#
|
5
|
+
# Wed Mar 11 17:09:17 JST 2009
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'spec_base'
|
9
|
+
|
10
|
+
|
11
|
+
describe Rufus::Lua::State do
|
12
|
+
|
13
|
+
describe 'Lua functions' do
|
14
|
+
|
15
|
+
before do
|
16
|
+
@s = Rufus::Lua::State.new
|
17
|
+
end
|
18
|
+
after do
|
19
|
+
@s.close
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'are returned as Rufus::Lua::Function instances' do
|
23
|
+
|
24
|
+
expect(@s.eval('return function () end').class).to eq Rufus::Lua::Function
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'are callable from Ruby' do
|
28
|
+
|
29
|
+
f = @s.eval(%{
|
30
|
+
f = function ()
|
31
|
+
return 77
|
32
|
+
end
|
33
|
+
return f
|
34
|
+
})
|
35
|
+
|
36
|
+
expect(f.call()).to eq 77.0
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'are callable even when they return multiple values' do
|
40
|
+
|
41
|
+
f = @s.eval(%{
|
42
|
+
f = function ()
|
43
|
+
return 77, 44
|
44
|
+
end
|
45
|
+
return f
|
46
|
+
})
|
47
|
+
|
48
|
+
expect(f.call()).to eq [ 77.0, 44.0 ]
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'are callable with arguments' do
|
52
|
+
|
53
|
+
f = @s.eval(%{
|
54
|
+
f = function (x)
|
55
|
+
return x * x
|
56
|
+
end
|
57
|
+
return f
|
58
|
+
})
|
59
|
+
|
60
|
+
expect(f.call(2)).to eq 4.0
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'are callable with boolean arguments' do
|
64
|
+
|
65
|
+
f = @s.eval(%{
|
66
|
+
f = function (x)
|
67
|
+
return x
|
68
|
+
end
|
69
|
+
return f
|
70
|
+
})
|
71
|
+
|
72
|
+
expect(f.call(true)).to eq true
|
73
|
+
expect(f.call(false)).to eq false
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'are callable with array arguments' do
|
77
|
+
|
78
|
+
f = @s.eval(%{
|
79
|
+
f = function (x)
|
80
|
+
return x
|
81
|
+
end
|
82
|
+
return f
|
83
|
+
})
|
84
|
+
|
85
|
+
expect(f.call(%w[ one two three ]).to_a).to eq %w[ one two three ]
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'are callable with multiple arguments' do
|
89
|
+
|
90
|
+
f = @s.eval(%{
|
91
|
+
f = function (x, y)
|
92
|
+
return x + y
|
93
|
+
end
|
94
|
+
return f
|
95
|
+
})
|
96
|
+
|
97
|
+
expect(f.call(1, 2)).to eq 3.0
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'are called with #to_lua\'ed Ruby arguments' do
|
101
|
+
|
102
|
+
f = @s.eval(%{
|
103
|
+
f = function (x)
|
104
|
+
return x
|
105
|
+
end
|
106
|
+
return f
|
107
|
+
})
|
108
|
+
|
109
|
+
t = Time.now
|
110
|
+
|
111
|
+
def t.to_lua
|
112
|
+
"lua:#{to_s}"
|
113
|
+
end
|
114
|
+
|
115
|
+
expect(f.call(t)).to eq t.to_lua
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
data/spec/gc_spec.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-lua
|
4
|
+
#
|
5
|
+
# Mon Mar 16 23:07:49 JST 2009
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'spec_base'
|
9
|
+
|
10
|
+
|
11
|
+
describe Rufus::Lua::State do
|
12
|
+
|
13
|
+
before do
|
14
|
+
@s = Rufus::Lua::State.new
|
15
|
+
end
|
16
|
+
after do
|
17
|
+
@s.close
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#gc_collect!' do
|
21
|
+
|
22
|
+
it 'raises when called on a closed Rufus::Lua::State instance' do
|
23
|
+
|
24
|
+
s = Rufus::Lua::State.new
|
25
|
+
s.close
|
26
|
+
expect(lambda { s.gc_collect! }).to raise_error(RuntimeError)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#gc_count' do
|
31
|
+
|
32
|
+
it 'returns an indication about the Lua interpreter memory usage' do
|
33
|
+
|
34
|
+
before_usage = @s.gc_count
|
35
|
+
@s.eval("return table.concat({ 'hello', 'from', 'Lua' }, ' ')")
|
36
|
+
after_usage = @s.gc_count
|
37
|
+
|
38
|
+
expect(after_usage).to be > before_usage
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|