sweet-moon 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +40 -0
  5. data/Gemfile +12 -0
  6. data/Gemfile.lock +61 -0
  7. data/README.md +1149 -0
  8. data/components/api.rb +83 -0
  9. data/components/injections/injections_503.rb +21 -0
  10. data/components/injections/injections_514.rb +29 -0
  11. data/components/injections/injections_542.rb +49 -0
  12. data/components/injections.rb +11 -0
  13. data/components/interpreters/50/function.rb +52 -0
  14. data/components/interpreters/50/interpreter.rb +105 -0
  15. data/components/interpreters/50/reader.rb +65 -0
  16. data/components/interpreters/50/table.rb +99 -0
  17. data/components/interpreters/50/writer.rb +45 -0
  18. data/components/interpreters/51/function.rb +52 -0
  19. data/components/interpreters/51/interpreter.rb +104 -0
  20. data/components/interpreters/51/reader.rb +65 -0
  21. data/components/interpreters/51/table.rb +60 -0
  22. data/components/interpreters/51/writer.rb +45 -0
  23. data/components/interpreters/54/function.rb +52 -0
  24. data/components/interpreters/54/interpreter.rb +100 -0
  25. data/components/interpreters/54/reader.rb +65 -0
  26. data/components/interpreters/54/table.rb +60 -0
  27. data/components/interpreters/54/writer.rb +45 -0
  28. data/components/interpreters.rb +11 -0
  29. data/components/io.rb +11 -0
  30. data/config/tests.sample.yml +15 -0
  31. data/controllers/api.rb +143 -0
  32. data/controllers/cli/cli.rb +32 -0
  33. data/controllers/cli/help.rb +24 -0
  34. data/controllers/cli/signatures.rb +179 -0
  35. data/controllers/cli/version.rb +14 -0
  36. data/controllers/interpreter.rb +68 -0
  37. data/controllers/state.rb +74 -0
  38. data/dsl/api.rb +31 -0
  39. data/dsl/cache.rb +118 -0
  40. data/dsl/concerns/fennel.rb +13 -0
  41. data/dsl/concerns/packages.rb +37 -0
  42. data/dsl/errors.rb +28 -0
  43. data/dsl/fennel.rb +47 -0
  44. data/dsl/global.rb +42 -0
  45. data/dsl/state.rb +104 -0
  46. data/dsl/sweet_moon.rb +53 -0
  47. data/logic/api.rb +17 -0
  48. data/logic/interpreter.rb +84 -0
  49. data/logic/interpreters/interpreter_50.rb +34 -0
  50. data/logic/interpreters/interpreter_51.rb +37 -0
  51. data/logic/interpreters/interpreter_54.rb +41 -0
  52. data/logic/io.rb +6 -0
  53. data/logic/options.rb +14 -0
  54. data/logic/shared_object.rb +52 -0
  55. data/logic/signature.rb +258 -0
  56. data/logic/signatures/ffi_types.rb +27 -0
  57. data/logic/signatures/signatures_322.rb +418 -0
  58. data/logic/signatures/signatures_401.rb +243 -0
  59. data/logic/signatures/signatures_503.rb +575 -0
  60. data/logic/signatures/signatures_514.rb +460 -0
  61. data/logic/signatures/signatures_542.rb +591 -0
  62. data/logic/spec.rb +13 -0
  63. data/logic/tables.rb +32 -0
  64. data/ports/in/dsl/sweet-moon/errors.rb +3 -0
  65. data/ports/in/dsl/sweet-moon.rb +1 -0
  66. data/ports/in/shell/sweet-moon +5 -0
  67. data/ports/in/shell.rb +21 -0
  68. data/ports/out/shell.rb +9 -0
  69. data/sweet-moon.gemspec +35 -0
  70. metadata +137 -0
data/components/api.rb ADDED
@@ -0,0 +1,83 @@
1
+ require 'ffi'
2
+
3
+ module Component
4
+ API = {
5
+ open!: ->(shared_objects) {
6
+ api = Module.new
7
+
8
+ api.extend FFI::Library
9
+
10
+ # TODO: Lua Constants
11
+ # attach_variable
12
+
13
+ if shared_objects.size > 1
14
+ # TODO: Dangerous
15
+ api.ffi_lib_flags(:global, :now)
16
+ else
17
+ api.ffi_lib_flags(:local, :now)
18
+ end
19
+
20
+ api.ffi_lib(*shared_objects.map { |o| o[:path] })
21
+
22
+ api
23
+ },
24
+
25
+ inject_callbacks!: ->(api, reference, injections) {
26
+ injections[:callbacks].each do |callback|
27
+ api.callback(*callback[:ffi])
28
+ reference[:signatures][:functions].each do |signature|
29
+ next unless callback[:overwrite][signature[:ffi].first]
30
+
31
+ signature[:ffi] = [
32
+ signature[:ffi].first, *callback[:overwrite][signature[:ffi].first]
33
+ ]
34
+ end
35
+ end
36
+ },
37
+
38
+ attach!: ->(api, reference, injections) {
39
+ API[:inject_callbacks!].(api, reference, injections)
40
+
41
+ signatures = {}
42
+
43
+ reference[:signatures][:functions].each do |signature|
44
+ exists = false
45
+
46
+ api.ffi_libraries.each do |ffi_library|
47
+ exists = true if ffi_library.find_function(signature[:ffi].first.to_s)
48
+ end
49
+
50
+ next unless exists
51
+
52
+ api.attach_function(*signature[:ffi])
53
+ signatures[signature[:ffi].first] = {
54
+ source: signature[:source],
55
+ input: signature[:ffi][1], output: signature[:ffi][2]
56
+ }
57
+ end
58
+
59
+ API[:inject_macros!].(api, signatures, reference, injections)
60
+ },
61
+
62
+ inject_macros!: ->(api, signatures, reference, injections) {
63
+ reference[:signatures][:macros].each do |macro_signature|
64
+ macro = injections[:macros][macro_signature[:name].to_sym]
65
+ next unless macro
66
+
67
+ missing = macro[:requires].detect { |function| !signatures[function] }
68
+
69
+ next if missing
70
+
71
+ api.define_singleton_method macro_signature[:name], macro[:injection]
72
+ api.define_method macro_signature[:name], macro[:injection]
73
+
74
+ signatures[macro_signature[:name].to_sym] = {
75
+ source: macro_signature[:source], macro: true,
76
+ requires: macro[:requires].map { |f| signatures[f] }
77
+ }
78
+ end
79
+
80
+ { api: api, signatures: signatures }
81
+ }
82
+ }
83
+ end
@@ -0,0 +1,21 @@
1
+ module Component
2
+ module V503
3
+ Injections = {
4
+ callbacks: [
5
+ {
6
+ ffi: [:cfunction, [:pointer], :int],
7
+ overwrite: {
8
+ lua_pushcclosure: [%i[pointer cfunction int], :void],
9
+ lua_tocfunction: [%i[pointer int], :cfunction]
10
+ }
11
+ }
12
+ ],
13
+ macros: {
14
+ lua_pop: {
15
+ requires: [:lua_settop],
16
+ injection: ->(l, n = 1) { lua_settop(l, -n - 1) }
17
+ }
18
+ }
19
+ }
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ module Component
2
+ module V514
3
+ Injections = {
4
+ callbacks: [
5
+ {
6
+ ffi: [:cfunction, [:pointer], :int],
7
+ overwrite: {
8
+ lua_pushcclosure: [%i[pointer cfunction int], :void],
9
+ lua_tocfunction: [%i[pointer int], :cfunction]
10
+ }
11
+ }
12
+ ],
13
+ macros: {
14
+ lua_pop: {
15
+ requires: [:lua_settop],
16
+ injection: ->(l, n = 1) { lua_settop(l, -n - 1) }
17
+ },
18
+ lua_tostring: {
19
+ requires: [:lua_tolstring],
20
+ injection: ->(l, i) { lua_tolstring(l, i, nil) }
21
+ },
22
+ luaL_typename: {
23
+ requires: %i[lua_typename lua_type],
24
+ injection: ->(l, i) { lua_typename(l, lua_type(l, i)) }
25
+ }
26
+ }
27
+ }
28
+ end
29
+ end
@@ -0,0 +1,49 @@
1
+ module Component
2
+ module V542
3
+ Injections = {
4
+ callbacks: [
5
+ {
6
+ ffi: [:cfunction, [:pointer], :int],
7
+ overwrite: {
8
+ lua_pushcclosure: [%i[pointer cfunction int], :void],
9
+ lua_tocfunction: [%i[pointer int], :cfunction]
10
+ }
11
+ }
12
+ ],
13
+ macros: {
14
+ lua_pop: {
15
+ requires: [:lua_settop],
16
+ injection: ->(l, n = 1) { lua_settop(l, -n - 1) }
17
+ },
18
+ lua_pcall: {
19
+ requires: [:lua_pcallk],
20
+ injection: ->(l, n, r, f) { lua_pcallk(l, n, r, f, 0, -1) }
21
+ },
22
+ luaL_loadfile: {
23
+ requires: [:luaL_loadfilex],
24
+ injection: ->(l, f) { luaL_loadfilex(l, f, nil) }
25
+ },
26
+ lua_tonumber: {
27
+ requires: [:lua_tonumberx],
28
+ injection: ->(l, i) { lua_tonumberx(l, i, nil) }
29
+ },
30
+ lua_tointeger: {
31
+ requires: [:lua_tointegerx],
32
+ injection: ->(l, i) { lua_tointegerx(l, i, nil) }
33
+ },
34
+ lua_tostring: {
35
+ requires: [:lua_tolstring],
36
+ injection: ->(l, i) { lua_tolstring(l, i, nil) }
37
+ },
38
+ luaL_typename: {
39
+ requires: %i[lua_typename lua_type],
40
+ injection: ->(l, i) { lua_typename(l, lua_type(l, i)) }
41
+ },
42
+ lua_insert: {
43
+ requires: %i[lua_rotate],
44
+ injection: ->(l, idx) { lua_rotate(l, idx, 1) }
45
+ }
46
+ }
47
+ }
48
+ end
49
+ end
@@ -0,0 +1,11 @@
1
+ require_relative 'injections/injections_503'
2
+ require_relative 'injections/injections_514'
3
+ require_relative 'injections/injections_542'
4
+
5
+ module Component
6
+ Injections = {
7
+ '5.0.3' => { version: '5.0.3', injections: V503::Injections },
8
+ '5.1.4' => { version: '5.1.4', injections: V514::Injections },
9
+ '5.4.2' => { version: '5.4.2', injections: V542::Injections }
10
+ }
11
+ end
@@ -0,0 +1,52 @@
1
+ require_relative '../../../logic/interpreters/interpreter_50'
2
+ require_relative '../../../dsl/errors'
3
+
4
+ require_relative 'writer'
5
+ require_relative 'reader'
6
+
7
+ module Component
8
+ module V50
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::V50::Interpreter[:LUA_REGISTRYINDEX]
24
+ )
25
+
26
+ { value: ->(input = [], output = 1) {
27
+ api.lua_rawgeti(
28
+ state, Logic::V50::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
46
+
47
+ result
48
+ }, pop: false }
49
+ }
50
+ }
51
+ end
52
+ end
@@ -0,0 +1,105 @@
1
+ require_relative '../../../logic/interpreters/interpreter_50'
2
+
3
+ require_relative 'reader'
4
+ require_relative 'writer'
5
+ require_relative 'table'
6
+
7
+ module Component
8
+ module V50
9
+ Interpreter = {
10
+ version: Logic::V50::Interpreter[:version],
11
+
12
+ create_state!: ->(api) {
13
+ state = api.lua_open
14
+ { state: state, error: state ? nil : :MemoryAllocation }
15
+ },
16
+
17
+ open_standard_libraries!: ->(api, state) {
18
+ api.luaopen_base(state)
19
+ api.luaopen_table(state)
20
+ api.luaopen_io(state)
21
+ api.luaopen_string(state)
22
+ api.luaopen_math(state)
23
+
24
+ api.lua_settop(state, -7 - 1)
25
+
26
+ { state: state }
27
+ },
28
+
29
+ load_file_and_push_chunck!: ->(api, state, path) {
30
+ result = api.luaL_loadfile(state, path)
31
+ { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
32
+ },
33
+
34
+ push_chunk!: ->(api, state, value) {
35
+ result = api.luaL_loadbuffer(state, value, value.size, value)
36
+
37
+ { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
38
+ },
39
+
40
+ set_table!: ->(api, state, variable, value) {
41
+ Table[:set!].(api, state, variable, value)
42
+ },
43
+
44
+ push_value!: ->(api, state, value) {
45
+ Writer[:push!].(api, state, value)
46
+ { state: state }
47
+ },
48
+
49
+ pop_and_set_as!: ->(api, state, variable) {
50
+ api.lua_pushstring(state, variable)
51
+ api.lua_insert(state, -2)
52
+ api.lua_settable(state, Logic::V50::Interpreter[:LUA_GLOBALSINDEX])
53
+ { state: state }
54
+ },
55
+
56
+ get_variable_and_push!: ->(api, state, variable, key = nil) {
57
+ api.lua_pushstring(state, variable.to_s)
58
+ api.lua_gettable(state, Logic::V50::Interpreter[:LUA_GLOBALSINDEX])
59
+
60
+ Table[:read_field_and_push!].(api, state, key, -1) unless key.nil?
61
+
62
+ { state: state }
63
+ },
64
+
65
+ call!: ->(api, state, inputs = 0, outputs = 1) {
66
+ result = api.lua_pcall(state, inputs, outputs, 0)
67
+ { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
68
+ },
69
+
70
+ read_and_pop!: ->(api, state, stack_index = -1, extra_pop: false) {
71
+ result = Component::V50::Reader[:read!].(api, state, stack_index)
72
+
73
+ api.lua_settop(state, -2) if result[:pop]
74
+ api.lua_settop(state, -2) if extra_pop
75
+
76
+ { state: state, output: result[:value] }
77
+ },
78
+
79
+ read_all!: ->(api, state) {
80
+ result = Reader[:read_all!].(api, state)
81
+
82
+ { state: state, output: result }
83
+ },
84
+
85
+ destroy_state!: ->(api, state) {
86
+ result = api.lua_close(state)
87
+
88
+ { state: nil, error: Interpreter[:_error].(api, state, result) }
89
+ },
90
+
91
+ _error: ->(api, state, code, options = {}) {
92
+ status = Logic::V50::Interpreter[:error][
93
+ Logic::V50::Interpreter[:status][code]
94
+ ] || :error
95
+
96
+ if code.is_a?(Numeric) && code >= 1
97
+ return { status: status } unless options[:pull]
98
+
99
+ { status: status,
100
+ value: Interpreter[:read_and_pop!].(api, state, -1)[:output] }
101
+ end
102
+ }
103
+ }
104
+ end
105
+ end
@@ -0,0 +1,65 @@
1
+ require 'ffi'
2
+
3
+ require_relative 'interpreter'
4
+ require_relative 'function'
5
+ require_relative 'table'
6
+
7
+ module Component
8
+ module V50
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
+ }
64
+ end
65
+ end
@@ -0,0 +1,99 @@
1
+ require_relative '../../../logic/tables'
2
+
3
+ require_relative 'writer'
4
+ require_relative 'reader'
5
+
6
+ module Component
7
+ module V50
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
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_and_push!: ->(api, state, expected_key, stack_index) {
54
+ stack_index = api.lua_gettop(state) if stack_index == -1
55
+
56
+ type = api.lua_typename(state, api.lua_type(state, stack_index)).read_string
57
+
58
+ api.lua_pushnil(state)
59
+
60
+ return nil if type != 'table'
61
+
62
+ result = nil
63
+
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)
67
+
68
+ api.lua_settop(state, -2) if value[:pop]
69
+
70
+ key_type = api.lua_typename(
71
+ state, api.lua_type(state, stack_index + 1)
72
+ ).read_string
73
+
74
+ if Table[:is_same_key].(key_type, key[:value], expected_key)
75
+ result = value[:value]
76
+ break
77
+ end
78
+
79
+ break if value[:type] == 'no value'
80
+ end
81
+
82
+ api.lua_settop(state, -2)
83
+
84
+ Writer[:push!].(api, state, result)
85
+ },
86
+
87
+ is_same_key: ->(lua_key_type, lua_key, ruby_key) {
88
+ lua_key == case lua_key_type
89
+ when 'string'
90
+ ruby_key.to_s
91
+ when 'number'
92
+ ruby_key.to_f
93
+ else
94
+ ruby_key
95
+ end
96
+ }
97
+ }
98
+ end
99
+ end
@@ -0,0 +1,45 @@
1
+ require_relative 'function'
2
+ require_relative 'table'
3
+
4
+ module Component
5
+ 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
+ }
44
+ end
45
+ end
@@ -0,0 +1,52 @@
1
+ require_relative '../../../logic/interpreters/interpreter_51'
2
+ require_relative '../../../dsl/errors'
3
+
4
+ require_relative 'writer'
5
+ require_relative 'reader'
6
+
7
+ module Component
8
+ 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
46
+
47
+ result
48
+ }, pop: false }
49
+ }
50
+ }
51
+ end
52
+ end