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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bc6ba34912c2d5c9e26b95b385e4a992b186b6adbe81e40e0e6068cc363a948
4
- data.tar.gz: 751f266193c94b533cf8f0b38f99745870688a2efd01e5277bb25d0aafe4b314
3
+ metadata.gz: 8e216a8bf96c191f08675bad6b2d4d9a1dceb9649a5e856ce4d6b4894e09b35e
4
+ data.tar.gz: b807eb9b92df1e53a0e0011f6132724c95b11a76dafab1073a46d2c5bf35c6ab
5
5
  SHA512:
6
- metadata.gz: 1fac3cd35cc1afd5cf1918f98326237203f9e12c631ccde66946a6496d24d90e69cf06a43413b1f58527c486f81f50098d7d866547389936becac5b6ba8eda84
7
- data.tar.gz: e14b5c3eecbdeefa68747f4b2cf8377c0b99289783bfd5dd3eec5c295368bea65eca70be594f4272777cbd811ecdb6a3fef36ce73103349831072d44851a51bb
6
+ metadata.gz: 538a7a773c11fe66a13c0be49efeb1f8d37da83f52a85d32fe8a7c52b3b590d155b0cdfb50efec3755181947db6a7b67a238b31c10bc382362b70301594949fb
7
+ data.tar.gz: 95d84ea3cf24919e4646c766f66302308f22392434ba5f76b0ae7743d4ef9ad3868d90b13b3d4bf26d58d7500d276b88be7ee26393818cf00950f08f4e6c4fc6
data/.rubocop.yml CHANGED
@@ -5,6 +5,9 @@ AllCops:
5
5
  Style/Documentation:
6
6
  Enabled: false
7
7
 
8
+ Lint/RescueException:
9
+ Exclude: ['components/interpreters/**/function.rb']
10
+
8
11
  Layout/LineLength:
9
12
  Max: 86
10
13
  Exclude: ['spec/**/*', 'logic/signatures/*']
data/README.md CHANGED
@@ -21,15 +21,18 @@ _Sweet Moon_ is a resilient solution that makes working with [Lua](https://www.l
21
21
  - [Tables, Arrays, and Hashes](#tables-arrays-and-hashes)
22
22
  - [Functions](#functions)
23
23
  - [Other Types](#other-types)
24
+ - [Lua Global vs Local Variables](#lua-global-vs-local-variables)
24
25
  - [_destroy_ and _clear_](#destroy-and-clear)
25
26
  - [Modules, Packages and LuaRocks](#modules-packages-and-luarocks)
26
27
  - [Integration with LuaRocks](#integration-with-luarocks)
27
28
  - [Fennel](#fennel)
28
29
  - [Fennel Usage](#fennel-usage)
30
+ - [Fennel Global vs Local Variables](#fennel-global-vs-local-variables)
29
31
  - [Fennel Setup](#fennel-setup)
30
32
  - [Integration with fnx](#integration-with-fnx)
31
33
  - [Global vs Isolated](#global-vs-isolated)
32
34
  - [Error Handling](#error-handling)
35
+ - [Ruby feat. Lua Errors](#ruby-feat-lua-errors)
33
36
  - [Where can I find .so files?](#where-can-i-find-so-files)
34
37
  - [Low-Level C API](#low-level-c-api)
35
38
  - [The API](#the-api)
@@ -69,7 +72,7 @@ gem install sweet-moon
69
72
  > **Disclaimer:** It's an early-stage project, and you should expect breaking changes.
70
73
 
71
74
  ```ruby
72
- gem 'sweet-moon', '~> 0.0.2'
75
+ gem 'sweet-moon', '~> 0.0.5'
73
76
  ```
74
77
 
75
78
  ```ruby
@@ -209,6 +212,7 @@ Compared to: [rufus-lua](https://github.com/jmettraux/rufus-lua), [YAML](https:/
209
212
  - [Tables, Arrays, and Hashes](#tables-arrays-and-hashes)
210
213
  - [Functions](#functions)
211
214
  - [Other Types](#other-types)
215
+ - [Lua Global vs Local Variables](#lua-global-vs-local-variables)
212
216
  - [_destroy_ and _clear_](#destroy-and-clear)
213
217
 
214
218
  ### Setup
@@ -389,6 +393,20 @@ state.eval('lua_value = {a = "text", b = 1.5, c = true}') # => nil
389
393
  state.get(:lua_value, :b) # => 1.5
390
394
  ```
391
395
 
396
+ With `set`, you can use a second parameter to set a field:
397
+
398
+ ```ruby
399
+ require 'sweet-moon'
400
+
401
+ state = SweetMoon::State.new
402
+
403
+ state.set(:myTable, {}) # => nil
404
+
405
+ state.set(:myTable, :a, 3) # => nil
406
+
407
+ state.eval('return myTable["a"]') # => 3
408
+ ```
409
+
392
410
  Caveats:
393
411
 
394
412
  - Ruby `Symbol` (e.g. `:value`) is converted to Lua `string`.
@@ -512,6 +530,24 @@ fennel_eval = state.get(:fennel_eval)
512
530
  fennel_eval.(['(+ 1 1)']) # => 2
513
531
  ```
514
532
 
533
+ #### Lua Global vs Local Variables
534
+
535
+ You can't exchange _local_ variables, only [_global_](https://www.lua.org/pil/1.2.html) ones:
536
+
537
+ ```ruby
538
+ require 'sweet-moon'
539
+
540
+ state = SweetMoon::State.new
541
+
542
+ state.eval('lua_value = "Lua Text"') # => nil
543
+
544
+ state.get('lua_value') # => 'Lua Text'
545
+
546
+ state.eval('local lua_b = "b"') # => nil
547
+
548
+ state.get('lua_b') # => nil
549
+ ```
550
+
515
551
  ## _destroy_ and _clear_
516
552
 
517
553
  You can destroy a state:
@@ -577,21 +613,21 @@ state.add_package_path('/home/me/my-lua-modules/?/init.lua')
577
613
 
578
614
  state.add_package_cpath('/home/me/my-lua-modules/?.so')
579
615
 
580
- state.add_package_path('/home/me/fennel.lua')
616
+ state.add_package_path('/home/me/fennel/?.lua')
581
617
 
582
- state.add_package_cpath('/home/me/lib.so')
618
+ state.add_package_cpath('/home/me/?.so')
583
619
 
584
620
  state.package_path
585
621
  # => ['./?.lua',
586
622
  # './?/init.lua',
587
623
  # '/home/me/my-lua-modules/?.lua',
588
624
  # '/home/me/my-lua-modules/?/init.lua',
589
- # '/home/me/fennel.lua']
625
+ # '/home/me/fennel/?.lua']
590
626
 
591
627
  state.package_cpath
592
628
  # => ['./?.so',
593
629
  # '/home/me/my-lua-modules/?.so',
594
- # '/home/me/lib.so']
630
+ # '/home/me/?.so']
595
631
  ```
596
632
 
597
633
  Requiring a module:
@@ -611,8 +647,8 @@ You can set packages in State constructors:
611
647
  require 'sweet-moon'
612
648
 
613
649
  SweetMoon::State.new(
614
- package_path: '/folder/lib.lua',
615
- package_cpath: '/lib/lib.so',
650
+ package_path: '/folder/lib/?.lua',
651
+ package_cpath: '/lib/lib/?.so',
616
652
  )
617
653
  ```
618
654
 
@@ -622,8 +658,8 @@ Also, you can add packages through the global config:
622
658
  require 'sweet-moon'
623
659
 
624
660
  SweetMoon.global.config(
625
- package_path: '/folder/lib.lua',
626
- package_cpath: '/lib/lib.so',
661
+ package_path: '/folder/lib/?.lua',
662
+ package_cpath: '/lib/lib/?.so',
627
663
  )
628
664
  ```
629
665
 
@@ -714,8 +750,8 @@ state = SweetMoon::State.new
714
750
 
715
751
  state.fennel.eval('(+ 1 2)') # => 3
716
752
 
717
- state.fennel.eval('(global mySum (fn [a b] (+ a b)))')
718
- state.fennel.eval('(mySum 2 3)') # => 5
753
+ state.fennel.eval('(set _G.mySum (fn [a b] (+ a b)))')
754
+ state.fennel.eval('(_G.mySum 2 3)') # => 5
719
755
 
720
756
  mySum = state.fennel.get(:mySum)
721
757
 
@@ -725,7 +761,7 @@ sum_list = -> (list) { list.sum }
725
761
 
726
762
  state.set('sumList', sum_list) # => nil
727
763
 
728
- state.fennel.eval('(sumList [2 3 5])') # => 10
764
+ state.fennel.eval('(_G.sumList [2 3 5])') # => 10
729
765
 
730
766
  state.fennel.load('file.fnl')
731
767
  ```
@@ -740,6 +776,49 @@ state = SweetMoon::State.new.fennel
740
776
  state.eval('(+ 1 2)') # => 3
741
777
  ```
742
778
 
779
+ ### Fennel Global vs Local Variables
780
+
781
+ Fennel encourages you to explicitly use the [_`_G`_](https://www.lua.org/manual/5.4/manual.html#pdf-_G) table to access global variables:
782
+
783
+ ```ruby
784
+ require 'sweet-moon'
785
+
786
+ fennel = SweetMoon::State.new.fennel
787
+
788
+ fennel.eval('(set _G.a? 2)')
789
+
790
+ fennel.get('a?') # => 2
791
+ fennel.get('_G', 'a?') # => 2
792
+
793
+ fennel.set('b', 3)
794
+
795
+ fennel.eval('(print _G.b)') # => 3
796
+ ```
797
+
798
+ Although older versions have the expression `(global name "value")`, it's deprecated, and you should avoid using that. _Sweet Moon_ has no commitments in supporting this deprecated expression, and you should prefer the `_G` way.
799
+
800
+ As is [true for Lua](#lua-global-vs-local-variables), you can't exchange _local_ variables, only [_global_](https://www.lua.org/pil/1.2.html) ones:
801
+
802
+ ```ruby
803
+ require 'sweet-moon'
804
+
805
+ fennel = SweetMoon::State.new.fennel
806
+
807
+ fennel.eval('(local name "value")')
808
+
809
+ fennel.get('name') # => nil
810
+
811
+ fennel.eval('(set _G.name "value")')
812
+
813
+ fennel.get('name') # => "value"
814
+
815
+ fennel.set('var-b', 35) # => nil
816
+
817
+ fennel.eval('var-b') # => nil
818
+
819
+ fennel.eval('_G.var-b') # => 35
820
+ ```
821
+
743
822
  ### Fennel Setup
744
823
 
745
824
  To ensure that the Fennel module is available, you can set up the [_LuaRocks_](#integration-withluarocks) integration or manually add the `package_path` for the module.
@@ -753,7 +832,7 @@ require 'sweet-moon'
753
832
 
754
833
  state = SweetMoon::State.new
755
834
 
756
- state.add_package_path('/folder/fennel.lua')
835
+ state.add_package_path('/folder/fennel/?.lua')
757
836
 
758
837
  state.fennel.eval('(+ 1 1)') # => 2
759
838
  ```
@@ -763,7 +842,7 @@ With the constructor:
763
842
  ```ruby
764
843
  require 'sweet-moon'
765
844
 
766
- fennel = SweetMoon::State.new(package_path: '/folder/fennel.lua').fennel
845
+ fennel = SweetMoon::State.new(package_path: '/folder/fennel/?.lua').fennel
767
846
 
768
847
  fennel.eval('(+ 1 1)') # => 2
769
848
  ```
@@ -773,7 +852,7 @@ With global:
773
852
  ```ruby
774
853
  require 'sweet-moon'
775
854
 
776
- SweetMoon.global.state.add_package_path('/folder/fennel.lua')
855
+ SweetMoon.global.state.add_package_path('/folder/fennel/?.lua')
777
856
 
778
857
  SweetMoon.global.state.fennel.eval('(+ 1 1)') # => 2
779
858
  ```
@@ -783,7 +862,7 @@ Alternatively:
783
862
  ```ruby
784
863
  require 'sweet-moon'
785
864
 
786
- SweetMoon.global.config(package_path: '/folder/fennel.lua')
865
+ SweetMoon.global.config(package_path: '/folder/fennel/?.lua')
787
866
 
788
867
  SweetMoon.global.state.fennel.eval('(+ 1 1)') # => 2
789
868
  ```
@@ -929,6 +1008,108 @@ rescue LuaRuntimeError => error
929
1008
  end
930
1009
  ```
931
1010
 
1011
+ ### Ruby feat. Lua Errors
1012
+
1013
+ Lua errors can be rescued inside Ruby:
1014
+
1015
+ ```lua
1016
+ -- source.lua
1017
+ error('error from lua')
1018
+ ```
1019
+
1020
+ ```ruby
1021
+ require 'sweet-moon'
1022
+ require 'sweet-moon/errors'
1023
+
1024
+ state = SweetMoon::State.new
1025
+
1026
+ begin
1027
+ state.load('source.lua')
1028
+ rescue LuaRuntimeError => e
1029
+ puts e.message
1030
+ # => source.lua:2: error from lua
1031
+ end
1032
+ ```
1033
+
1034
+ Ruby errors can be handled inside Lua:
1035
+
1036
+ ```ruby
1037
+ require 'sweet-moon'
1038
+
1039
+ state = SweetMoon::State.new
1040
+
1041
+ state.set(:rubyFn, -> { raise 'error from ruby' })
1042
+
1043
+ state.load('source.lua')
1044
+ ```
1045
+
1046
+ ```lua
1047
+ -- source.lua
1048
+ local status, err = pcall(rubyFn)
1049
+
1050
+ print(status) -- => false
1051
+
1052
+ print(err)
1053
+ -- [string " return function (...)..."]:5: RuntimeError: error from ruby stack traceback:
1054
+ -- [string " return function (...)..."]:5: in function 'rubyFn'
1055
+ -- [C]: in function 'pcall'
1056
+ -- source.lua:2: in main chunk
1057
+ ```
1058
+
1059
+ Ruby errors not handled inside Lua can be rescued inside Ruby again, with an additional Lua backtrace:
1060
+
1061
+ ```lua
1062
+ -- source.lua
1063
+ a = 1
1064
+
1065
+ rubyFn()
1066
+ ```
1067
+
1068
+ ```ruby
1069
+ require 'sweet-moon'
1070
+
1071
+ state = SweetMoon::State.new
1072
+
1073
+ state.set(:rubyFn, -> { raise 'error from ruby' })
1074
+
1075
+ begin
1076
+ state.load('source.lua')
1077
+ rescue RuntimeError => e
1078
+ puts e.message # => error from ruby
1079
+
1080
+ puts e.backtrace.last
1081
+ # => source.lua:4: in main chunk
1082
+ end
1083
+ ```
1084
+
1085
+ Lua errors inside Lua functions can be rescued inside Ruby:
1086
+
1087
+ ```lua
1088
+ -- source.lua
1089
+ function luaFn()
1090
+ error('lua function error')
1091
+ end
1092
+ ```
1093
+
1094
+ ```ruby
1095
+ require 'sweet-moon'
1096
+ require 'sweet-moon/errors'
1097
+
1098
+ state = SweetMoon::State.new
1099
+
1100
+ state.load('source.lua')
1101
+
1102
+ lua_fn = state.get(:luaFn)
1103
+
1104
+ begin
1105
+ lua_fn.()
1106
+ rescue LuaRuntimeError => e
1107
+ puts e.message # => "source.lua:3: lua function error"
1108
+ end
1109
+ ```
1110
+
1111
+ For Fennel, all the examples above are equally true, with additional stack traceback as well.
1112
+
932
1113
  ## Where can I find .so files?
933
1114
 
934
1115
  Due to the Lua's popularity, you likely have it already on your system, and _Sweet Moon_ will be able to find the files by itself.
@@ -6,7 +6,8 @@ module Component
6
6
  ffi: [:cfunction, [:pointer], :int],
7
7
  overwrite: {
8
8
  lua_pushcclosure: [%i[pointer cfunction int], :void],
9
- lua_tocfunction: [%i[pointer int], :cfunction]
9
+ lua_tocfunction: [%i[pointer int], :cfunction],
10
+ lua_atpanic: [%i[pointer cfunction], :cfunction]
10
11
  }
11
12
  }
12
13
  ],
@@ -6,7 +6,8 @@ module Component
6
6
  ffi: [:cfunction, [:pointer], :int],
7
7
  overwrite: {
8
8
  lua_pushcclosure: [%i[pointer cfunction int], :void],
9
- lua_tocfunction: [%i[pointer int], :cfunction]
9
+ lua_tocfunction: [%i[pointer int], :cfunction],
10
+ lua_atpanic: [%i[pointer cfunction], :cfunction]
10
11
  }
11
12
  }
12
13
  ],
@@ -6,7 +6,8 @@ module Component
6
6
  ffi: [:cfunction, [:pointer], :int],
7
7
  overwrite: {
8
8
  lua_pushcclosure: [%i[pointer cfunction int], :void],
9
- lua_tocfunction: [%i[pointer int], :cfunction]
9
+ lua_tocfunction: [%i[pointer int], :cfunction],
10
+ lua_atpanic: [%i[pointer cfunction], :cfunction]
10
11
  }
11
12
  }
12
13
  ],
@@ -1,52 +1,19 @@
1
- require_relative '../../../logic/interpreters/interpreter_50'
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 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
- }
5
+ Function = Component::V54::Function
6
+
7
+ LUA_HANDLER = <<LUA
8
+ return function (...)
9
+ result = _ruby(unpack(arg))
10
+
11
+ if result['error'] then
12
+ error(result['output'])
13
+ else
14
+ return result['output']
15
+ end
16
+ end
17
+ LUA
51
18
  end
52
19
  end
@@ -1,91 +1,113 @@
1
1
  require_relative '../../../logic/interpreters/interpreter_50'
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 V50
9
10
  Interpreter = {
10
11
  version: Logic::V50::Interpreter[:version],
12
+ logic: Logic::V50,
11
13
 
12
14
  create_state!: ->(api) {
13
15
  state = api.lua_open
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.luaopen_base(state)
19
- api.luaopen_table(state)
20
- api.luaopen_io(state)
21
- api.luaopen_string(state)
22
- api.luaopen_math(state)
21
+ api.luaopen_base(state[:lua])
22
+ api.luaopen_table(state[:lua])
23
+ api.luaopen_io(state[:lua])
24
+ api.luaopen_string(state[:lua])
25
+ api.luaopen_math(state[:lua])
23
26
 
24
- api.lua_settop(state, -7 - 1)
27
+ api.lua_settop(state[:lua], -7 - 1)
25
28
 
26
29
  { state: state }
27
30
  },
28
31
 
29
32
  load_file_and_push_chunck!: ->(api, state, path) {
30
- result = api.luaL_loadfile(state, path)
33
+ result = api.luaL_loadfile(state[:lua], path)
31
34
  { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
32
35
  },
33
36
 
34
37
  push_chunk!: ->(api, state, value) {
35
- result = api.luaL_loadbuffer(state, value, value.size, value)
38
+ result = api.luaL_loadbuffer(state[:lua], value, value.size, value)
36
39
 
37
40
  { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
38
41
  },
39
42
 
40
- set_table!: ->(api, state, variable, value) {
41
- Table[:set!].(api, state, variable, value)
43
+ set_table!: ->(api, state) {
44
+ result = api.lua_settable(state[:lua], -3)
45
+
46
+ api.lua_settop(state[:lua], -2)
47
+
48
+ { state: state,
49
+ error: Interpreter[:_error].(api, state, result, pull: false) }
42
50
  },
43
51
 
44
52
  push_value!: ->(api, state, value) {
45
- Writer[:push!].(api, state, value)
53
+ Writer[:push!].(api, state, Component::V50, value)
46
54
  { state: state }
47
55
  },
48
56
 
49
57
  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])
58
+ api.lua_pushstring(state[:lua], variable)
59
+ api.lua_insert(state[:lua], -2)
60
+ api.lua_settable(state[:lua], Logic::V50::Interpreter[:LUA_GLOBALSINDEX])
53
61
  { state: state }
54
62
  },
55
63
 
56
64
  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])
65
+ extra_pop = true
66
+ if variable == '_G'
67
+ variable = key
68
+ key = nil
69
+ extra_pop = false
70
+ end
59
71
 
60
- Table[:read_field_and_push!].(api, state, key, -1) unless key.nil?
72
+ api.lua_pushstring(state[:lua], variable.to_s)
73
+ api.lua_gettable(state[:lua], Logic::V50::Interpreter[:LUA_GLOBALSINDEX])
61
74
 
62
- { state: state }
75
+ unless key.nil?
76
+ Table[:read_field_and_push!].(api, state, Component::V50, key,
77
+ -1)
78
+ end
79
+
80
+ { state: state, extra_pop: extra_pop }
63
81
  },
64
82
 
65
83
  call!: ->(api, state, inputs = 0, outputs = 1) {
66
- result = api.lua_pcall(state, inputs, outputs, 0)
84
+ result = api.lua_pcall(state[:lua], inputs, outputs, 0)
67
85
  { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
68
86
  },
69
87
 
70
88
  read_and_pop!: ->(api, state, stack_index = -1, extra_pop: false) {
71
- result = Component::V50::Reader[:read!].(api, state, stack_index)
89
+ result = Component::V50::Reader[:read!].(api, state, Component::V50,
90
+ stack_index)
72
91
 
73
- api.lua_settop(state, -2) if result[:pop]
74
- api.lua_settop(state, -2) if extra_pop
92
+ api.lua_settop(state[:lua], -2) if result[:pop]
93
+ api.lua_settop(state[:lua], -2) if extra_pop
75
94
 
76
95
  { state: state, output: result[:value] }
77
96
  },
78
97
 
79
98
  read_all!: ->(api, state) {
80
- result = Reader[:read_all!].(api, state)
99
+ result = Reader[:read_all!].(api, state, Component::V50)
81
100
 
82
101
  { state: state, output: result }
83
102
  },
84
103
 
85
104
  destroy_state!: ->(api, state) {
86
- result = api.lua_close(state)
105
+ result = api.lua_close(state[:lua])
106
+
107
+ state.delete(:lua)
108
+ state.delete(:avoid_gc)
87
109
 
88
- { state: nil, error: Interpreter[:_error].(api, state, result) }
110
+ { state: nil, error: Interpreter[:_error].(api, nil, result) }
89
111
  },
90
112
 
91
113
  _error: ->(api, state, code, options = {}) {
@@ -94,7 +116,7 @@ module Component
94
116
  ] || :error
95
117
 
96
118
  if code.is_a?(Numeric) && code >= 1
97
- return { status: status } unless options[:pull]
119
+ return { status: status } unless options[:pull] && state
98
120
 
99
121
  { status: status,
100
122
  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 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
- }
5
+ Reader = Component::V54::Reader
64
6
  end
65
7
  end