sweet-moon 0.0.2 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,82 +6,47 @@ require_relative 'reader'
6
6
  module Component
7
7
  module V50
8
8
  Table = {
9
- push!: ->(api, state, list, stack_index = -1) {
10
- stack_index = api.lua_gettop(state) if stack_index == -1
11
-
12
- api.lua_newtable(state)
13
-
14
- if list.is_a? Hash
15
- list.each_key do |key|
16
- Writer[:push!].(api, state, key)
17
- Writer[:push!].(api, state, list[key])
18
- api.lua_settable(state, stack_index + 1)
19
- end
20
- else
21
- list.each_with_index do |value, index|
22
- Writer[:push!].(api, state, index + 1)
23
- Writer[:push!].(api, state, value)
24
- api.lua_settable(state, stack_index + 1)
25
- end
26
- end
9
+ create_table!: ->(api, state, _list) {
10
+ api.lua_newtable(state[:lua])
27
11
  },
28
12
 
29
- read!: ->(api, state, stack_index) {
30
- stack_index = api.lua_gettop(state) if stack_index == -1
31
-
32
- type = api.lua_typename(state, api.lua_type(state, stack_index)).read_string
33
-
34
- api.lua_pushnil(state)
35
-
36
- return nil if type != 'table'
37
-
38
- tuples = []
39
-
40
- while api.lua_next(state, stack_index).positive?
41
- value = Reader[:read!].(api, state, stack_index + 2)
42
- key = Reader[:read!].(api, state, stack_index + 1)
43
- api.lua_settop(state, -2) if value[:pop]
44
-
45
- tuples << [key[:value], value[:value]]
46
-
47
- break if value[:type] == 'no value'
48
- end
49
-
50
- { value: Logic::Tables[:to_hash_or_array].(tuples), pop: true }
51
- },
13
+ push!: Component::V54::Table[:push!],
14
+ read!: Component::V54::Table[:read!],
52
15
 
53
- read_field_and_push!: ->(api, state, expected_key, stack_index) {
54
- stack_index = api.lua_gettop(state) if stack_index == -1
16
+ read_field_and_push!: ->(api, state, component, expected_key, stack_index) {
17
+ stack_index = api.lua_gettop(state[:lua]) if stack_index == -1
55
18
 
56
- type = api.lua_typename(state, api.lua_type(state, stack_index)).read_string
19
+ type = api.lua_typename(
20
+ state[:lua], api.lua_type(state[:lua], stack_index)
21
+ ).read_string
57
22
 
58
- api.lua_pushnil(state)
23
+ api.lua_pushnil(state[:lua])
59
24
 
60
25
  return nil if type != 'table'
61
26
 
62
27
  result = nil
63
28
 
64
- while api.lua_next(state, stack_index).positive?
65
- value = Reader[:read!].(api, state, stack_index + 2)
66
- key = Reader[:read!].(api, state, stack_index + 1)
29
+ while api.lua_next(state[:lua], stack_index).positive?
30
+ value = component::Reader[:read!].(api, state, component, stack_index + 2)
31
+ key = component::Reader[:read!].(api, state, component, stack_index + 1)
67
32
 
68
- api.lua_settop(state, -2) if value[:pop]
33
+ api.lua_settop(state[:lua], -2) if value[:pop]
69
34
 
70
35
  key_type = api.lua_typename(
71
- state, api.lua_type(state, stack_index + 1)
36
+ state[:lua], api.lua_type(state[:lua], stack_index + 1)
72
37
  ).read_string
73
38
 
74
- if Table[:is_same_key].(key_type, key[:value], expected_key)
39
+ if component::Table[:is_same_key].(key_type, key[:value], expected_key)
75
40
  result = value[:value]
76
41
  break
77
42
  end
78
43
 
79
- break if value[:type] == 'no value'
44
+ break if value[:type] == 'no value' || key[:value].instance_of?(Proc)
80
45
  end
81
46
 
82
- api.lua_settop(state, -2)
47
+ api.lua_settop(state[:lua], -2)
83
48
 
84
- Writer[:push!].(api, state, result)
49
+ component::Writer[:push!].(api, state, component, result)
85
50
  },
86
51
 
87
52
  is_same_key: ->(lua_key_type, lua_key, ruby_key) {
@@ -1,45 +1,7 @@
1
- require_relative 'function'
2
- require_relative 'table'
1
+ require_relative '../54/writer'
3
2
 
4
3
  module Component
5
4
  module V50
6
- Writer = {
7
- push!: ->(api, state, value) {
8
- case Writer[:_to_lua_type].(value)
9
- when 'string'
10
- api.lua_pushstring(state, value.to_s)
11
- when 'number'
12
- api.lua_pushnumber(state, value)
13
- when 'integer'
14
- if api.respond_to? :lua_pushinteger
15
- api.lua_pushinteger(state, value)
16
- else
17
- api.lua_pushnumber(state, value)
18
- end
19
- when 'nil'
20
- api.lua_pushnil(state)
21
- when 'boolean'
22
- api.lua_pushboolean(state, value ? 1 : 0)
23
- when 'table'
24
- Table[:push!].(api, state, value)
25
- when 'function'
26
- Function[:push!].(api, state, value)
27
- else
28
- api.lua_pushstring(
29
- state, "#<#{value.class}:0x#{format('%016x', value.object_id)}>"
30
- )
31
- end
32
- },
33
-
34
- _to_lua_type: ->(value) {
35
- return 'nil' if value.nil?
36
- return 'function' if value.is_a?(Proc)
37
- return 'integer' if value.is_a? Integer
38
- return 'number' if value.is_a? Float
39
- return 'table' if value.is_a?(Hash) || value.is_a?(Array)
40
- return 'string' if value.is_a?(String) || value.instance_of?(Symbol)
41
- return 'boolean' if [true, false].include? value
42
- }
43
- }
5
+ Writer = Component::V54::Writer
44
6
  end
45
7
  end
@@ -1,52 +1,9 @@
1
- require_relative '../../../logic/interpreters/interpreter_51'
2
- require_relative '../../../dsl/errors'
3
-
4
- require_relative 'writer'
5
- require_relative 'reader'
1
+ require_relative '../54/function'
6
2
 
7
3
  module Component
8
4
  module V51
9
- Function = {
10
- push!: ->(api, state, closure) {
11
- handler = ->(current_state) {
12
- input = Reader[:read_all!].(api, current_state)
13
- result = closure.(*input)
14
- Writer[:push!].(api, current_state, result)
15
- return 1
16
- }
17
-
18
- api.lua_pushcclosure(state, handler, 0)
19
- },
20
-
21
- read!: ->(api, state, _stack_index) {
22
- reference = api.luaL_ref(
23
- state, Logic::V51::Interpreter[:LUA_REGISTRYINDEX]
24
- )
25
-
26
- { value: ->(input = [], output = 1) {
27
- api.lua_rawgeti(
28
- state, Logic::V51::Interpreter[:LUA_REGISTRYINDEX], reference
29
- )
30
-
31
- input.each do |value|
32
- Writer[:push!].(api, state, value)
33
- end
34
-
35
- result = Interpreter[:call!].(api, state, input.size, output)
36
-
37
- if result[:error]
38
- raise SweetMoon::Errors::SweetMoonErrorHelper.for(
39
- result[:error][:status]
40
- ), result[:error][:value]
41
- end
42
-
43
- result = Reader[:read_all!].(api, state)
44
-
45
- return result.first if output == 1
5
+ Function = Component::V54::Function
46
6
 
47
- result
48
- }, pop: false }
49
- }
50
- }
7
+ LUA_HANDLER = Component::V54::LUA_HANDLER
51
8
  end
52
9
  end
@@ -1,90 +1,101 @@
1
1
  require_relative '../../../logic/interpreters/interpreter_51'
2
2
 
3
+ require_relative 'function'
3
4
  require_relative 'reader'
4
- require_relative 'writer'
5
5
  require_relative 'table'
6
+ require_relative 'writer'
6
7
 
7
8
  module Component
8
9
  module V51
9
10
  Interpreter = {
10
11
  version: Logic::V51::Interpreter[:version],
12
+ logic: Logic::V51,
11
13
 
12
14
  create_state!: ->(api) {
13
15
  state = api.luaL_newstate
14
- { state: state, error: state ? nil : :MemoryAllocation }
16
+ { state: { lua: state, avoid_gc: [], ruby_error_info: nil },
17
+ error: state ? nil : :MemoryAllocation }
15
18
  },
16
19
 
17
20
  open_standard_libraries!: ->(api, state) {
18
- api.luaL_openlibs(state)
19
-
21
+ api.luaL_openlibs(state[:lua])
20
22
  { state: state }
21
23
  },
22
24
 
23
25
  load_file_and_push_chunck!: ->(api, state, path) {
24
- result = api.luaL_loadfile(state, path)
26
+ result = api.luaL_loadfile(state[:lua], path)
25
27
  { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
26
28
  },
27
29
 
28
30
  push_chunk!: ->(api, state, value) {
29
- result = api.luaL_loadstring(state, value)
31
+ result = api.luaL_loadstring(state[:lua], value)
30
32
  { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
31
33
  },
32
34
 
33
- set_table!: ->(api, state, variable, value) {
34
- Table[:set!].(api, state, variable, value)
35
+ set_table!: ->(api, state) {
36
+ result = api.lua_settable(state[:lua], -3)
37
+
38
+ api.lua_settop(state[:lua], -2)
39
+
40
+ { state: state,
41
+ error: Interpreter[:_error].(api, state, result, pull: false) }
35
42
  },
36
43
 
37
44
  push_value!: ->(api, state, value) {
38
- Writer[:push!].(api, state, value)
45
+ Writer[:push!].(api, state, Component::V51, value)
39
46
  { state: state }
40
47
  },
41
48
 
42
49
  pop_and_set_as!: ->(api, state, variable) {
43
- api.lua_pushstring(state, variable)
44
- api.lua_insert(state, -2)
45
- api.lua_settable(state, Logic::V51::Interpreter[:LUA_GLOBALSINDEX])
50
+ api.lua_pushstring(state[:lua], variable)
51
+ api.lua_insert(state[:lua], -2)
52
+ api.lua_settable(state[:lua], Logic::V51::Interpreter[:LUA_GLOBALSINDEX])
46
53
  { state: state }
47
54
  },
48
55
 
49
56
  get_variable_and_push!: ->(api, state, variable, key = nil) {
50
- api.lua_pushstring(state, variable.to_s)
51
- api.lua_gettable(state, Logic::V51::Interpreter[:LUA_GLOBALSINDEX])
57
+ api.lua_pushstring(state[:lua], variable.to_s)
58
+ api.lua_gettable(state[:lua], Logic::V51::Interpreter[:LUA_GLOBALSINDEX])
52
59
 
53
60
  unless key.nil?
54
- if api.lua_typename(state, api.lua_type(state, -1)).read_string == 'table'
55
- Table[:read_field!].(api, state, key, -1)
61
+ if api.lua_typename(state[:lua],
62
+ api.lua_type(state[:lua], -1)).read_string == 'table'
63
+ Table[:read_field!].(api, state, Component::V51, key, -1)
56
64
  else
57
- api.lua_pushnil(state)
65
+ api.lua_pushnil(state[:lua])
58
66
  end
59
67
  end
60
68
 
61
- { state: state }
69
+ { state: state, extra_pop: true }
62
70
  },
63
71
 
64
72
  call!: ->(api, state, inputs = 0, outputs = 1) {
65
- result = api.lua_pcall(state, inputs, outputs, 0)
73
+ result = api.lua_pcall(state[:lua], inputs, outputs, 0)
66
74
  { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
67
75
  },
68
76
 
69
77
  read_and_pop!: ->(api, state, stack_index = -1, extra_pop: false) {
70
- result = Component::V51::Reader[:read!].(api, state, stack_index)
78
+ result = Reader[:read!].(api, state, Component::V51, stack_index)
71
79
 
72
- api.lua_settop(state, -2) if result[:pop]
73
- api.lua_settop(state, -2) if extra_pop
80
+ api.lua_settop(state[:lua], -2) if result[:pop]
81
+ api.lua_settop(state[:lua], -2) if extra_pop
74
82
 
75
83
  { state: state, output: result[:value] }
76
84
  },
77
85
 
78
86
  read_all!: ->(api, state) {
79
- result = Reader[:read_all!].(api, state)
87
+ result = Reader[:read_all!].(api, state, Component::V51)
80
88
 
81
89
  { state: state, output: result }
82
90
  },
83
91
 
84
92
  destroy_state!: ->(api, state) {
85
- result = api.lua_close(state)
93
+ result = api.lua_close(state[:lua])
94
+
95
+ state.delete(:lua)
96
+ state.delete(:avoid_gc)
86
97
 
87
- { state: nil, error: Interpreter[:_error].(api, state, result) }
98
+ { state: nil, error: Interpreter[:_error].(api, nil, result) }
88
99
  },
89
100
 
90
101
  _error: ->(api, state, code, options = {}) {
@@ -93,7 +104,7 @@ module Component
93
104
  ] || :error
94
105
 
95
106
  if code.is_a?(Numeric) && code >= 2
96
- return { status: status } unless options[:pull]
107
+ return { status: status } unless options[:pull] && state
97
108
 
98
109
  { status: status,
99
110
  value: Interpreter[:read_and_pop!].(api, state, -1)[:output] }
@@ -1,65 +1,7 @@
1
- require 'ffi'
2
-
3
- require_relative 'interpreter'
4
- require_relative 'function'
5
- require_relative 'table'
1
+ require_relative '../54/reader'
6
2
 
7
3
  module Component
8
4
  module V51
9
- Reader = {
10
- read_all!: ->(api, state) {
11
- (1..api.lua_gettop(state)).map do
12
- Interpreter[:read_and_pop!].(api, state)[:output]
13
- end.reverse
14
- },
15
-
16
- read!: ->(api, state, stack_index = -1) {
17
- stack_index = api.lua_gettop(state) if stack_index == -1
18
-
19
- type = api.lua_typename(state, api.lua_type(state, stack_index)).read_string
20
-
21
- case type
22
- when 'string'
23
- Reader[:read_string!].(api, state, stack_index)
24
- when 'number'
25
- Reader[:read_number!].(api, state, stack_index)
26
- when 'no value'
27
- { value: nil, pop: true, type: type }
28
- when 'nil'
29
- { value: nil, pop: true }
30
- when 'boolean'
31
- Reader[:read_boolean!].(api, state, stack_index)
32
- when 'table'
33
- Table[:read!].(api, state, stack_index)
34
- when 'function'
35
- Function[:read!].(api, state, stack_index)
36
- else
37
- # none nil boolean lightuserdata number
38
- # string table function userdata thread
39
- { value: "#{type}: 0x#{api.lua_topointer(state, stack_index).address}",
40
- type: type, pop: true }
41
- end
42
- },
43
-
44
- read_string!: ->(api, state, stack_index) {
45
- { value: api.lua_tostring(state, stack_index).read_string,
46
- pop: true }
47
- },
48
-
49
- read_number!: ->(api, state, stack_index) {
50
- if api.respond_to?(:lua_isinteger) &&
51
- api.respond_to?(:lua_tointeger) &&
52
- api.lua_isinteger(state, stack_index) == 1
53
-
54
- return { value: api.lua_tointeger(state, stack_index), pop: true }
55
- end
56
-
57
- { value: api.lua_tonumber(state, stack_index), pop: true }
58
- },
59
-
60
- read_boolean!: ->(api, state, stack_index) {
61
- { value: api.lua_toboolean(state, stack_index) == 1, pop: true }
62
- }
63
- }
5
+ Reader = Component::V54::Reader
64
6
  end
65
7
  end
@@ -1,60 +1,7 @@
1
- require_relative '../../../logic/tables'
2
-
3
- require_relative 'writer'
4
- require_relative 'reader'
1
+ require_relative '../54/table'
5
2
 
6
3
  module Component
7
4
  module V51
8
- Table = {
9
- push!: ->(api, state, list, stack_index = -1) {
10
- stack_index = api.lua_gettop(state) if stack_index == -1
11
-
12
- api.lua_createtable(state, list.size, 0)
13
-
14
- if list.is_a? Hash
15
- list.each_key do |key|
16
- Writer[:push!].(api, state, key)
17
- Writer[:push!].(api, state, list[key])
18
- api.lua_settable(state, stack_index + 1)
19
- end
20
- else
21
- list.each_with_index do |value, index|
22
- Writer[:push!].(api, state, index + 1)
23
- Writer[:push!].(api, state, value)
24
- api.lua_settable(state, stack_index + 1)
25
- end
26
- end
27
- },
28
-
29
- read!: ->(api, state, stack_index) {
30
- stack_index = api.lua_gettop(state) if stack_index == -1
31
-
32
- type = api.lua_typename(state, api.lua_type(state, stack_index)).read_string
33
-
34
- api.lua_pushnil(state)
35
-
36
- return nil if type != 'table'
37
-
38
- tuples = []
39
-
40
- while api.lua_next(state, stack_index).positive?
41
- value = Reader[:read!].(api, state, stack_index + 2)
42
- key = Reader[:read!].(api, state, stack_index + 1)
43
- api.lua_settop(state, -2) if value[:pop]
44
-
45
- tuples << [key[:value], value[:value]]
46
-
47
- break if value[:type] == 'no value'
48
- end
49
-
50
- { value: Logic::Tables[:to_hash_or_array].(tuples), pop: true }
51
- },
52
-
53
- read_field!: ->(api, state, expected_key, stack_index) {
54
- expected_key = expected_key.to_s if expected_key.is_a? Symbol
55
-
56
- api.lua_getfield(state, stack_index, expected_key)
57
- }
58
- }
5
+ Table = Component::V54::Table
59
6
  end
60
7
  end
@@ -1,45 +1,7 @@
1
- require_relative 'function'
2
- require_relative 'table'
1
+ require_relative '../54/writer'
3
2
 
4
3
  module Component
5
4
  module V51
6
- Writer = {
7
- push!: ->(api, state, value) {
8
- case Writer[:_to_lua_type].(value)
9
- when 'string'
10
- api.lua_pushstring(state, value.to_s)
11
- when 'number'
12
- api.lua_pushnumber(state, value)
13
- when 'integer'
14
- if api.respond_to? :lua_pushinteger
15
- api.lua_pushinteger(state, value)
16
- else
17
- api.lua_pushnumber(state, value)
18
- end
19
- when 'nil'
20
- api.lua_pushnil(state)
21
- when 'boolean'
22
- api.lua_pushboolean(state, value ? 1 : 0)
23
- when 'table'
24
- Table[:push!].(api, state, value)
25
- when 'function'
26
- Function[:push!].(api, state, value)
27
- else
28
- api.lua_pushstring(
29
- state, "#<#{value.class}:0x#{format('%016x', value.object_id)}>"
30
- )
31
- end
32
- },
33
-
34
- _to_lua_type: ->(value) {
35
- return 'nil' if value.nil?
36
- return 'function' if value.is_a?(Proc)
37
- return 'integer' if value.is_a? Integer
38
- return 'number' if value.is_a? Float
39
- return 'table' if value.is_a?(Hash) || value.is_a?(Array)
40
- return 'string' if value.is_a?(String) || value.instance_of?(Symbol)
41
- return 'boolean' if [true, false].include? value
42
- }
43
- }
5
+ Writer = Component::V54::Writer
44
6
  end
45
7
  end
@@ -1,52 +1,111 @@
1
1
  require_relative '../../../logic/interpreters/interpreter_54'
2
2
  require_relative '../../../dsl/errors'
3
3
 
4
- require_relative 'writer'
4
+ require_relative 'interpreter'
5
5
  require_relative 'reader'
6
+ require_relative 'writer'
6
7
 
7
8
  module Component
8
9
  module V54
9
10
  Function = {
10
- push!: ->(api, state, closure) {
11
- handler = ->(current_state) {
12
- input = Reader[:read_all!].(api, current_state)
13
- result = closure.(*input)
14
- Writer[:push!].(api, current_state, result)
11
+ push!: ->(api, state, component, closure) {
12
+ handler = component::Function[:build_handler!].(
13
+ api, state, component, closure
14
+ )
15
+
16
+ state[:avoid_gc] << handler
17
+
18
+ lua_name = "_sweet_moon_ruby_#{handler.object_id}"
19
+
20
+ api.lua_pushcclosure(state[:lua], handler, 0)
21
+ component::Interpreter[:pop_and_set_as!].(api, state, lua_name)
22
+
23
+ result = component::Interpreter[:push_chunk!].(
24
+ api, state, component::LUA_HANDLER.sub('_ruby', lua_name)
25
+ )
26
+
27
+ unless result[:error].nil?
28
+ raise SweetMoon::Errors::SweetMoonErrorHelper.for(
29
+ result[:error][:status]
30
+ ), result[:error][:value]
31
+ end
32
+
33
+ component::Interpreter[:call!].(api, state, 0, 1)
34
+ },
35
+
36
+ build_handler!: ->(api, state, component, closure) {
37
+ ->(current_state) {
38
+ updated_state = state.merge(lua: current_state)
39
+ input = component::Reader[:read_all!].(api, updated_state, component)
40
+ begin
41
+ result = closure.(*input)
42
+ component::Writer[:push!].(
43
+ api, updated_state, component, { error: nil, output: result }
44
+ )
45
+ rescue Exception => e
46
+ state[:ruby_error_info] = e
47
+ component::Writer[:push!].(
48
+ api, updated_state, component, {
49
+ error: true, output: "#{e.class}: #{e.message}"
50
+ }
51
+ )
52
+ end
15
53
  return 1
16
54
  }
17
-
18
- api.lua_pushcclosure(state, handler, 0)
19
55
  },
20
56
 
21
- read!: ->(api, state, _stack_index) {
22
- reference = api.luaL_ref(
23
- state, Logic::V54::Interpreter[:LUA_REGISTRYINDEX]
24
- )
57
+ read!: ->(api, state, component, _stack_index) {
58
+ lua_registry_index = component::Interpreter[:logic]::Interpreter[
59
+ :LUA_REGISTRYINDEX
60
+ ]
61
+
62
+ reference = api.luaL_ref(state[:lua], lua_registry_index)
25
63
 
26
64
  { value: ->(input = [], output = 1) {
27
- api.lua_rawgeti(
28
- state, Logic::V54::Interpreter[:LUA_REGISTRYINDEX], reference
29
- )
65
+ api.lua_rawgeti(state[:lua], lua_registry_index, reference)
30
66
 
31
67
  input.each do |value|
32
- Writer[:push!].(api, state, value)
68
+ component::Writer[:push!].(api, state, component, value)
33
69
  end
34
70
 
35
- result = Interpreter[:call!].(api, state, input.size, output)
71
+ result = component::Interpreter[:call!].(api, state, input.size, output)
36
72
 
37
- if result[:error]
38
- raise SweetMoon::Errors::SweetMoonErrorHelper.for(
39
- result[:error][:status]
40
- ), result[:error][:value]
41
- end
73
+ component::Function[:raise_error!].(state, result) if result[:error]
42
74
 
43
- result = Reader[:read_all!].(api, state)
75
+ result = component::Reader[:read_all!].(api, state, component)
44
76
 
45
77
  return result.first if output == 1
46
78
 
47
79
  result
48
80
  }, pop: false }
81
+ },
82
+
83
+ raise_error!: ->(state, result) {
84
+ if state[:ruby_error_info].nil?
85
+ raise SweetMoon::Errors::SweetMoonErrorHelper.for(
86
+ result[:error][:status]
87
+ ), result[:error][:value]
88
+ else
89
+ ruby_error = state[:ruby_error_info]
90
+ state[:ruby_error_info] = nil
91
+
92
+ raise SweetMoon::Errors::SweetMoonErrorHelper.merge_traceback!(
93
+ ruby_error, result[:error][:value]
94
+ )
95
+ end
49
96
  }
50
97
  }
98
+
99
+ LUA_HANDLER = <<LUA
100
+ return function (...)
101
+ result = _ruby(...)
102
+
103
+ if result['error'] then
104
+ error(result['output'] .. ' ' .. debug.traceback())
105
+ else
106
+ return result['output']
107
+ end
108
+ end
109
+ LUA
51
110
  end
52
111
  end