sweet-moon 0.0.3 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,55 +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
- updated_state = state.merge(lua: current_state)
13
- input = Reader[:read_all!].(api, updated_state)
14
- result = closure.(*input)
15
- Writer[:push!].(api, updated_state, result)
16
- return 1
17
- }
11
+ push!: ->(api, state, component, closure) {
12
+ handler = component::Function[:build_handler!].(
13
+ api, state, component, closure
14
+ )
18
15
 
19
16
  state[:avoid_gc] << handler
20
17
 
18
+ lua_name = "_sweet_moon_ruby_#{handler.object_id}"
19
+
21
20
  api.lua_pushcclosure(state[:lua], handler, 0)
22
- },
21
+ component::Interpreter[:pop_and_set_as!].(api, state, lua_name)
23
22
 
24
- read!: ->(api, state, _stack_index) {
25
- reference = api.luaL_ref(
26
- state[:lua], Logic::V54::Interpreter[:LUA_REGISTRYINDEX]
23
+ result = component::Interpreter[:push_chunk!].(
24
+ api, state, component::LUA_HANDLER.sub('_ruby', lua_name)
27
25
  )
28
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
53
+ return 1
54
+ }
55
+ },
56
+
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)
63
+
29
64
  { value: ->(input = [], output = 1) {
30
- api.lua_rawgeti(
31
- state[:lua], Logic::V54::Interpreter[:LUA_REGISTRYINDEX], reference
32
- )
65
+ api.lua_rawgeti(state[:lua], lua_registry_index, reference)
33
66
 
34
67
  input.each do |value|
35
- Writer[:push!].(api, state, value)
68
+ component::Writer[:push!].(api, state, component, value)
36
69
  end
37
70
 
38
- result = Interpreter[:call!].(api, state, input.size, output)
71
+ result = component::Interpreter[:call!].(api, state, input.size, output)
39
72
 
40
- if result[:error]
41
- raise SweetMoon::Errors::SweetMoonErrorHelper.for(
42
- result[:error][:status]
43
- ), result[:error][:value]
44
- end
73
+ component::Function[:raise_error!].(state, result) if result[:error]
45
74
 
46
- result = Reader[:read_all!].(api, state)
75
+ result = component::Reader[:read_all!].(api, state, component)
47
76
 
48
77
  return result.first if output == 1
49
78
 
50
79
  result
51
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
52
96
  }
53
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
54
110
  end
55
111
  end
@@ -1,17 +1,19 @@
1
1
  require_relative '../../../logic/interpreters/interpreter_54'
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 V54
9
10
  Interpreter = {
10
11
  version: Logic::V54::Interpreter[:version],
12
+ logic: Logic::V54,
11
13
 
12
14
  create_state!: ->(api) {
13
15
  state = api.luaL_newstate
14
- { state: { lua: state, avoid_gc: [] },
16
+ { state: { lua: state, avoid_gc: [], ruby_error_info: nil },
15
17
  error: state ? nil : :MemoryAllocation }
16
18
  },
17
19
 
@@ -30,12 +32,17 @@ module Component
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::V54, value)
39
46
  { state: state }
40
47
  },
41
48
 
@@ -50,13 +57,13 @@ module Component
50
57
  unless key.nil?
51
58
  if api.lua_typename(state[:lua],
52
59
  api.lua_type(state[:lua], -1)).read_string == 'table'
53
- Table[:read_field!].(api, state, key, -1)
60
+ Table[:read_field!].(api, state, Component::V54, key, -1)
54
61
  else
55
62
  api.lua_pushnil(state[:lua])
56
63
  end
57
64
  end
58
65
 
59
- { state: state }
66
+ { state: state, extra_pop: true }
60
67
  },
61
68
 
62
69
  call!: ->(api, state, inputs = 0, outputs = 1) {
@@ -65,7 +72,8 @@ module Component
65
72
  },
66
73
 
67
74
  read_and_pop!: ->(api, state, stack_index = -1, extra_pop: false) {
68
- result = Component::V54::Reader[:read!].(api, state, stack_index)
75
+ result = Component::V54::Reader[:read!].(api, state, Component::V54,
76
+ stack_index)
69
77
 
70
78
  api.lua_settop(state[:lua], -2) if result[:pop]
71
79
  api.lua_settop(state[:lua], -2) if extra_pop
@@ -74,7 +82,7 @@ module Component
74
82
  },
75
83
 
76
84
  read_all!: ->(api, state) {
77
- result = Reader[:read_all!].(api, state)
85
+ result = Reader[:read_all!].(api, state, Component::V54)
78
86
 
79
87
  { state: state, output: result }
80
88
  },
@@ -7,33 +7,34 @@ require_relative 'table'
7
7
  module Component
8
8
  module V54
9
9
  Reader = {
10
- read_all!: ->(api, state) {
10
+ read_all!: ->(api, state, component) {
11
11
  (1..api.lua_gettop(state[:lua])).map do
12
- Interpreter[:read_and_pop!].(api, state)[:output]
12
+ component::Interpreter[:read_and_pop!].(api, state)[:output]
13
13
  end.reverse
14
14
  },
15
15
 
16
- read!: ->(api, state, stack_index = -1) {
16
+ read!: ->(api, state, component, stack_index = -1) {
17
17
  stack_index = api.lua_gettop(state[:lua]) if stack_index == -1
18
18
 
19
- type = api.lua_typename(state[:lua],
20
- api.lua_type(state[:lua], stack_index)).read_string
19
+ type = api.lua_typename(
20
+ state[:lua], api.lua_type(state[:lua], stack_index)
21
+ ).read_string
21
22
 
22
23
  case type
23
24
  when 'string'
24
- Reader[:read_string!].(api, state, stack_index)
25
+ component::Reader[:read_string!].(api, state, stack_index)
25
26
  when 'number'
26
- Reader[:read_number!].(api, state, stack_index)
27
+ component::Reader[:read_number!].(api, state, stack_index)
27
28
  when 'no value'
28
29
  { value: nil, pop: true, type: type }
29
30
  when 'nil'
30
31
  { value: nil, pop: true }
31
32
  when 'boolean'
32
- Reader[:read_boolean!].(api, state, stack_index)
33
+ component::Reader[:read_boolean!].(api, state, stack_index)
33
34
  when 'table'
34
- Table[:read!].(api, state, stack_index)
35
+ component::Table[:read!].(api, state, component, stack_index)
35
36
  when 'function'
36
- Function[:read!].(api, state, stack_index)
37
+ component::Function[:read!].(api, state, component, stack_index)
37
38
  else
38
39
  # none nil boolean lightuserdata number
39
40
  # string table function userdata thread
@@ -6,31 +6,36 @@ require_relative 'reader'
6
6
  module Component
7
7
  module V54
8
8
  Table = {
9
- push!: ->(api, state, list, stack_index = -1) {
9
+ create_table!: ->(api, state, list) {
10
+ api.lua_createtable(state[:lua], list.size, 0)
11
+ },
12
+
13
+ push!: ->(api, state, component, list, stack_index = -1) {
10
14
  stack_index = api.lua_gettop(state[:lua]) if stack_index == -1
11
15
 
12
- api.lua_createtable(state[:lua], list.size, 0)
16
+ component::Table[:create_table!].(api, state, list)
13
17
 
14
18
  if list.is_a? Hash
15
19
  list.each_key do |key|
16
- Writer[:push!].(api, state, key)
17
- Writer[:push!].(api, state, list[key])
20
+ component::Writer[:push!].(api, state, component, key)
21
+ component::Writer[:push!].(api, state, component, list[key])
18
22
  api.lua_settable(state[:lua], stack_index + 1)
19
23
  end
20
24
  else
21
25
  list.each_with_index do |value, index|
22
- Writer[:push!].(api, state, index + 1)
23
- Writer[:push!].(api, state, value)
26
+ component::Writer[:push!].(api, state, component, index + 1)
27
+ component::Writer[:push!].(api, state, component, value)
24
28
  api.lua_settable(state[:lua], stack_index + 1)
25
29
  end
26
30
  end
27
31
  },
28
32
 
29
- read!: ->(api, state, stack_index) {
33
+ read!: ->(api, state, component, stack_index) {
30
34
  stack_index = api.lua_gettop(state[:lua]) if stack_index == -1
31
35
 
32
- type = api.lua_typename(state[:lua],
33
- api.lua_type(state[:lua], stack_index)).read_string
36
+ type = api.lua_typename(
37
+ state[:lua], api.lua_type(state[:lua], stack_index)
38
+ ).read_string
34
39
 
35
40
  api.lua_pushnil(state[:lua])
36
41
 
@@ -39,8 +44,8 @@ module Component
39
44
  tuples = []
40
45
 
41
46
  while api.lua_next(state[:lua], stack_index).positive?
42
- value = Reader[:read!].(api, state, stack_index + 2)
43
- key = Reader[:read!].(api, state, stack_index + 1)
47
+ value = component::Reader[:read!].(api, state, component, stack_index + 2)
48
+ key = component::Reader[:read!].(api, state, component, stack_index + 1)
44
49
  api.lua_settop(state[:lua], -2) if value[:pop]
45
50
 
46
51
  tuples << [key[:value], value[:value]]
@@ -51,7 +56,7 @@ module Component
51
56
  { value: Logic::Tables[:to_hash_or_array].(tuples), pop: true }
52
57
  },
53
58
 
54
- read_field!: ->(api, state, expected_key, stack_index) {
59
+ read_field!: ->(api, state, _component, expected_key, stack_index) {
55
60
  expected_key = expected_key.to_s if expected_key.is_a? Symbol
56
61
 
57
62
  api.lua_getfield(state[:lua], stack_index, expected_key)
@@ -4,8 +4,8 @@ require_relative 'table'
4
4
  module Component
5
5
  module V54
6
6
  Writer = {
7
- push!: ->(api, state, value) {
8
- case Writer[:_to_lua_type].(value)
7
+ push!: ->(api, state, component, value) {
8
+ case component::Writer[:_to_lua_type].(value)
9
9
  when 'string'
10
10
  api.lua_pushstring(state[:lua], value.to_s)
11
11
  when 'number'
@@ -21,9 +21,9 @@ module Component
21
21
  when 'boolean'
22
22
  api.lua_pushboolean(state[:lua], value ? 1 : 0)
23
23
  when 'table'
24
- Table[:push!].(api, state, value)
24
+ component::Table[:push!].(api, state, component, value)
25
25
  when 'function'
26
- Function[:push!].(api, state, value)
26
+ component::Function[:push!].(api, state, component, value)
27
27
  else
28
28
  api.lua_pushstring(
29
29
  state[:lua], "#<#{value.class}:0x#{format('%016x', value.object_id)}>"
@@ -1,41 +1,44 @@
1
1
  # Available at https://github.com/gbaptista/sweet-moon-test
2
2
 
3
+ fennel-dev: '/home/me/sweet-moon-test/fennel/dev/?.lua'
4
+
3
5
  luarocks:
6
+ expected: ['dkjson', 'supernova', 'readline']
4
7
  path:
5
8
  - /home/me/.luarocks/share/lua/5.4/?.lua
6
9
  - /home/me/.luarocks/share/lua/5.4/?/init.lua
10
+ cpath:
7
11
  - /home/me/.luarocks/lib/lua/5.4/?.so
8
- expected: ['supernova', 'dkjson', 'lfs']
9
12
 
10
13
  jit:2.0.5:
11
14
  description: 'Lua Jit 2.0.5 + Fennel 1.0.0'
12
15
  shared_object: /home/me/sweet-moon-test/libluajit.so.2.0.5
13
- fennel: /home/me/sweet-moon-test/fennel-100.lua
16
+ fennel: /home/me/sweet-moon-test/fennel/100/?.lua
14
17
 
15
18
  5.4.4:
16
19
  description: 'Lua 5.4.4 + Fennel 1.0.0'
17
20
  shared_object: /home/me/sweet-moon-test/liblua.so.5.4.4
18
- fennel: /home/me/sweet-moon-test/fennel-100.lua
21
+ fennel: /home/me/sweet-moon-test/fennel/100/?.lua
19
22
 
20
23
  5.4.2:
21
24
  description: 'Lua 5.4.2 + Fennel 1.0.0'
22
25
  shared_object: /home/me/sweet-moon-test/liblua.so.5.4.2
23
- fennel: /home/me/sweet-moon-test/fennel-100.lua
26
+ fennel: /home/me/sweet-moon-test/fennel/100/?.lua
24
27
 
25
28
  5.3.3:
26
29
  description: 'Lua 5.3.3'
27
30
  shared_object: /home/me/sweet-moon-test/liblua.so.5.3.3
28
- fennel: /home/me/sweet-moon-test/fennel-100.lua
31
+ fennel: /home/me/sweet-moon-test/fennel/100/?.lua
29
32
 
30
33
  5.2.4:
31
34
  description: 'Lua 5.2.4'
32
35
  shared_object: /home/me/sweet-moon-test/liblua.so.5.2.4
33
- fennel: /home/me/sweet-moon-test/fennel-100.lua
36
+ fennel: /home/me/sweet-moon-test/fennel/100/?.lua
34
37
 
35
38
  5.1.5:
36
39
  description: 'Lua 5.1.5'
37
40
  shared_object: /home/me/sweet-moon-test/liblua.so.5.1.5
38
- fennel: /home/me/sweet-moon-test/fennel-100.lua
41
+ fennel: /home/me/sweet-moon-test/fennel/100/?.lua
39
42
 
40
43
  5.0.3:
41
44
  description: 'Lua 5.0.3'
data/controllers/api.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require_relative '../components/injections'
2
2
  require_relative '../components/api'
3
+ require_relative '../components/default'
3
4
  require_relative '../components/io'
4
5
  require_relative '../dsl/errors'
5
6
 
@@ -11,7 +12,9 @@ module Controller
11
12
  handle!: ->(options) {
12
13
  shared_objects = API[:elect_shared_objects!].(options[:shared_objects])
13
14
 
14
- api = Component::API[:open!].(shared_objects)
15
+ api = Component::API[:open!].(
16
+ shared_objects, options, Component::Default.instance.options
17
+ )
15
18
 
16
19
  api_reference = API[:elect_api_reference!].(
17
20
  api.ffi_libraries, options[:api_reference]
data/controllers/state.rb CHANGED
@@ -26,23 +26,48 @@ module Controller
26
26
  },
27
27
 
28
28
  get!: ->(api, interpreter, state, variable, key = nil) {
29
+ if key.nil?
30
+ key = variable
31
+ variable = '_G'
32
+ end
33
+
34
+ State[:_get_key!].(api, interpreter, state, variable, key)
35
+ },
36
+
37
+ _get_key!: ->(api, interpreter, state, variable, key) {
29
38
  result = State[:_check!].(
30
39
  interpreter[:get_variable_and_push!].(api, state, variable, key)
31
40
  )
32
41
 
33
- result = State[:_check!].(interpreter[:read_and_pop!].(
34
- api, result[:state], -1, extra_pop: !key.nil?
35
- ))
42
+ result = State[:_check!].(
43
+ interpreter[:read_and_pop!].(
44
+ api, result[:state], -1, extra_pop: result[:extra_pop]
45
+ )
46
+ )
36
47
 
37
48
  { state: result[:state], output: result[:output] }
38
49
  },
39
50
 
40
- set!: ->(api, interpreter, state, variable, value) {
41
- result = State[:_check!].(interpreter[:push_value!].(api, state, value))
42
-
43
- result = State[:_check!].(
44
- interpreter[:pop_and_set_as!].(api, result[:state], variable.to_s)
45
- )
51
+ set!: ->(api, interpreter, state, variable, key_or_value, value = nil) {
52
+ if value.nil?
53
+ result = State[:_check!].(interpreter[:push_value!].(api, state,
54
+ key_or_value))
55
+
56
+ result = State[:_check!].(
57
+ interpreter[:pop_and_set_as!].(api, result[:state], variable.to_s)
58
+ )
59
+ else
60
+ result = State[:_check!].(
61
+ interpreter[:get_variable_and_push!].(api, state, variable)
62
+ )
63
+
64
+ result = State[:_check!].(interpreter[:push_value!].(api, result[:state],
65
+ key_or_value))
66
+ result = State[:_check!].(interpreter[:push_value!].(api, result[:state],
67
+ value))
68
+
69
+ result = State[:_check!].(interpreter[:set_table!].(api, result[:state]))
70
+ end
46
71
 
47
72
  { state: result[:state], output: result[:output] }
48
73
  },
@@ -62,10 +87,20 @@ module Controller
62
87
  },
63
88
 
64
89
  _check!: ->(result) {
90
+ ruby_error = result[:state] && result[:state][:ruby_error_info]
91
+
92
+ result[:state][:ruby_error_info] = nil if ruby_error
93
+
65
94
  if result[:error]
66
- raise SweetMoon::Errors::SweetMoonErrorHelper.for(
67
- result[:error][:status]
68
- ), result[:error][:value]
95
+ if ruby_error
96
+ raise SweetMoon::Errors::SweetMoonErrorHelper.merge_traceback!(
97
+ ruby_error, result[:error][:value]
98
+ )
99
+ else
100
+ raise SweetMoon::Errors::SweetMoonErrorHelper.for(
101
+ result[:error][:status]
102
+ ), result[:error][:value]
103
+ end
69
104
  end
70
105
 
71
106
  result
data/dsl/api.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require_relative '../components/default'
2
+
1
3
  module DSL
2
4
  class Api
3
5
  attr_reader :functions, :meta
@@ -7,13 +9,31 @@ module DSL
7
9
 
8
10
  @functions = @component[:signatures].keys
9
11
 
10
- @meta = Struct.new(
11
- *@component[:meta][:elected].keys
12
- ).new(*@component[:meta][:elected].values)
12
+ build_meta
13
13
 
14
14
  extend @component[:api]
15
15
  end
16
16
 
17
+ def build_global_ffi
18
+ global_ffi = Component::Default.instance.options[:global_ffi]
19
+
20
+ unless @component[:meta][:options][:global_ffi].nil?
21
+ global_ffi = @component[:meta][:options][:global_ffi]
22
+ end
23
+
24
+ global_ffi
25
+ end
26
+
27
+ def build_meta
28
+ meta_data = @component[:meta][:elected].clone
29
+
30
+ meta_data[:global_ffi] = build_global_ffi
31
+
32
+ @meta = Struct.new(
33
+ *meta_data.keys
34
+ ).new(*meta_data.values)
35
+ end
36
+
17
37
  def signature_for(function)
18
38
  @component[:signatures][function.to_sym]
19
39
  end