sweet-moon 0.0.1 → 0.0.4

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: 1e1ed99acf5622e7a68168e97a5543a952da6cbd057b29d35dcac167cdd7ed3e
4
- data.tar.gz: 30ffaf5cd2c96429114950db5e44c39c328cdefeb711df44eba1d5b288d34a1e
3
+ metadata.gz: bdfabe100158948ea2c29fadca09e82cd9567d71230627f6bd0e8ba3a04f523d
4
+ data.tar.gz: 3bb2925b0ef437c3942a837a67bb94261d89c9aaf5a011973dcf4b98db07e6b9
5
5
  SHA512:
6
- metadata.gz: 375db63fb25932d6d1e0d1fda599c996a62efd2f51691528785e34b2bba37078dcb98db1f05f669375759852671cf0792aed27110fea91e8d351406ba219823f
7
- data.tar.gz: bd4732726abfb6f8ce2dcf0b4bc81d858bb03d9cde60610f0e02372e29c2951cf47f2b2d6cebd3f2eb5d25b23daa29ec6097f8603e578d4dfcd572486b3c1eee
6
+ metadata.gz: 582a792771b05e59a577349070709e78bb2a569ef14cdb955fb2666e826eb401ba4aa4e7b19297c30fd64f98eda244d656caf2e904f9c1af95e971807aed8820
7
+ data.tar.gz: 38307987e564f998b40b2792fd97a3e107095d6e46992689663d63d67bf248dfc16c3a8838f8461bf7a8765857e7b5c04da4e4ac3c636cd6a419abb85bab2e5b
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2022 Guilherme Baptista
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # Sweet Moon
2
+ [![Gem Version](https://badge.fury.io/rb/sweet-moon.svg)](https://badge.fury.io/rb/sweet-moon)
2
3
 
3
4
  _Sweet Moon_ is a resilient solution that makes working with [Lua](https://www.lua.org) / [Fennel](https://fennel-lang.org) from [Ruby](https://www.ruby-lang.org) and vice versa a delightful experience.
4
5
 
@@ -20,12 +21,15 @@ _Sweet Moon_ is a resilient solution that makes working with [Lua](https://www.l
20
21
  - [Tables, Arrays, and Hashes](#tables-arrays-and-hashes)
21
22
  - [Functions](#functions)
22
23
  - [Other Types](#other-types)
24
+ - [Lua Global vs Local Variables](#lua-global-vs-local-variables)
23
25
  - [_destroy_ and _clear_](#destroy-and-clear)
24
26
  - [Modules, Packages and LuaRocks](#modules-packages-and-luarocks)
25
27
  - [Integration with LuaRocks](#integration-with-luarocks)
26
28
  - [Fennel](#fennel)
27
29
  - [Fennel Usage](#fennel-usage)
30
+ - [Fennel Global vs Local Variables](#fennel-global-vs-local-variables)
28
31
  - [Fennel Setup](#fennel-setup)
32
+ - [Integration with fnx](#integration-with-fnx)
29
33
  - [Global vs Isolated](#global-vs-isolated)
30
34
  - [Error Handling](#error-handling)
31
35
  - [Where can I find .so files?](#where-can-i-find-so-files)
@@ -38,6 +42,9 @@ _Sweet Moon_ is a resilient solution that makes working with [Lua](https://www.l
38
42
  - [Lua 5.4](#lua-54)
39
43
  - [Lua 4.0](#lua-40)
40
44
  - [Development](#development)
45
+ - [Tests Setup](#tests-setup)
46
+ - [Running](#running)
47
+ - [Supporting New Versions](#supporting-new-versions)
41
48
 
42
49
  ## Supported Versions
43
50
 
@@ -64,7 +71,7 @@ gem install sweet-moon
64
71
  > **Disclaimer:** It's an early-stage project, and you should expect breaking changes.
65
72
 
66
73
  ```ruby
67
- gem 'sweet-moon', '~> 0.0.1'
74
+ gem 'sweet-moon', '~> 0.0.4'
68
75
  ```
69
76
 
70
77
  ```ruby
@@ -204,6 +211,7 @@ Compared to: [rufus-lua](https://github.com/jmettraux/rufus-lua), [YAML](https:/
204
211
  - [Tables, Arrays, and Hashes](#tables-arrays-and-hashes)
205
212
  - [Functions](#functions)
206
213
  - [Other Types](#other-types)
214
+ - [Lua Global vs Local Variables](#lua-global-vs-local-variables)
207
215
  - [_destroy_ and _clear_](#destroy-and-clear)
208
216
 
209
217
  ### Setup
@@ -384,6 +392,20 @@ state.eval('lua_value = {a = "text", b = 1.5, c = true}') # => nil
384
392
  state.get(:lua_value, :b) # => 1.5
385
393
  ```
386
394
 
395
+ With `set`, you can use a second parameter to set a field:
396
+
397
+ ```ruby
398
+ require 'sweet-moon'
399
+
400
+ state = SweetMoon::State.new
401
+
402
+ state.set(:myTable, {}) # => nil
403
+
404
+ state.set(:myTable, :a, 3) # => nil
405
+
406
+ state.eval('return myTable["a"]') # => 3
407
+ ```
408
+
387
409
  Caveats:
388
410
 
389
411
  - Ruby `Symbol` (e.g. `:value`) is converted to Lua `string`.
@@ -507,6 +529,24 @@ fennel_eval = state.get(:fennel_eval)
507
529
  fennel_eval.(['(+ 1 1)']) # => 2
508
530
  ```
509
531
 
532
+ #### Lua Global vs Local Variables
533
+
534
+ You can't exchange _local_ variables, only [_global_](https://www.lua.org/pil/1.2.html) ones:
535
+
536
+ ```ruby
537
+ require 'sweet-moon'
538
+
539
+ state = SweetMoon::State.new
540
+
541
+ state.eval('lua_value = "Lua Text"') # => nil
542
+
543
+ state.get('lua_value') # => 'Lua Text'
544
+
545
+ state.eval('local lua_b = "b"') # => nil
546
+
547
+ state.get('lua_b') # => nil
548
+ ```
549
+
510
550
  ## _destroy_ and _clear_
511
551
 
512
552
  You can destroy a state:
@@ -552,8 +592,8 @@ require 'sweet-moon'
552
592
 
553
593
  state = SweetMoon::State.new
554
594
 
555
- state.eval('package.path = package.path .. ";/my-modules/?.lua"')
556
- state.eval('package.cpath = package.cpath .. ";/my-modules/?.so"')
595
+ state.eval('package.path = "/my-modules/?.lua;" .. package.path')
596
+ state.eval('package.cpath = "/my-modules/?.so;" .. package.cpath')
557
597
 
558
598
  state.eval('some_package = require("my_module")')
559
599
  ```
@@ -682,7 +722,7 @@ For global:
682
722
  ```ruby
683
723
  require 'sweet-moon'
684
724
 
685
- SweetMoon.global.config.new(
725
+ SweetMoon.global.config(
686
726
  package_path: [
687
727
  '/home/me/.luarocks/share/lua/5.4/?.lua',
688
728
  '/home/me/.luarocks/share/lua/5.4/?/init.lua'
@@ -709,8 +749,8 @@ state = SweetMoon::State.new
709
749
 
710
750
  state.fennel.eval('(+ 1 2)') # => 3
711
751
 
712
- state.fennel.eval('(global mySum (fn [a b] (+ a b)))')
713
- state.fennel.eval('(mySum 2 3)') # => 5
752
+ state.fennel.eval('(set _G.mySum (fn [a b] (+ a b)))')
753
+ state.fennel.eval('(_G.mySum 2 3)') # => 5
714
754
 
715
755
  mySum = state.fennel.get(:mySum)
716
756
 
@@ -720,7 +760,7 @@ sum_list = -> (list) { list.sum }
720
760
 
721
761
  state.set('sumList', sum_list) # => nil
722
762
 
723
- state.fennel.eval('(sumList [2 3 5])') # => 10
763
+ state.fennel.eval('(_G.sumList [2 3 5])') # => 10
724
764
 
725
765
  state.fennel.load('file.fnl')
726
766
  ```
@@ -735,6 +775,49 @@ state = SweetMoon::State.new.fennel
735
775
  state.eval('(+ 1 2)') # => 3
736
776
  ```
737
777
 
778
+ ### Fennel Global vs Local Variables
779
+
780
+ Fennel encourages you to explicitly use the [_`_G`_](https://www.lua.org/manual/5.4/manual.html#pdf-_G) table to access global variables:
781
+
782
+ ```ruby
783
+ require 'sweet-moon'
784
+
785
+ fennel = SweetMoon::State.new.fennel
786
+
787
+ fennel.eval('(set _G.a? 2)')
788
+
789
+ fennel.get('a?') # => 2
790
+ fennel.get('_G', 'a?') # => 2
791
+
792
+ fennel.set('b', 3)
793
+
794
+ fennel.eval('(print _G.b)') # => 3
795
+ ```
796
+
797
+ 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.
798
+
799
+ 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:
800
+
801
+ ```ruby
802
+ require 'sweet-moon'
803
+
804
+ fennel = SweetMoon::State.new.fennel
805
+
806
+ fennel.eval('(local name "value")')
807
+
808
+ fennel.get('name') # => nil
809
+
810
+ fennel.eval('(set _G.name "value")')
811
+
812
+ fennel.get('name') # => "value"
813
+
814
+ fennel.set('var-b', 35) # => nil
815
+
816
+ fennel.eval('var-b') # => nil
817
+
818
+ fennel.eval('_G.var-b') # => 35
819
+ ```
820
+
738
821
  ### Fennel Setup
739
822
 
740
823
  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.
@@ -783,6 +866,28 @@ SweetMoon.global.config(package_path: '/folder/fennel.lua')
783
866
  SweetMoon.global.state.fennel.eval('(+ 1 1)') # => 2
784
867
  ```
785
868
 
869
+ ### Integration with fnx
870
+
871
+ [fnx](https://github.com/gbaptista/fnx) is a package manager for the Fennel language.
872
+
873
+ After installing `fnx` and configuring it for [_Embedding_](https://github.com/gbaptista/fnx#embedding), you can:
874
+
875
+ ```ruby
876
+ require 'sweet-moon'
877
+
878
+ fennel = SweetMoon::State.new.fennel
879
+
880
+ fennel.eval('(let [fnx (require :fnx)] (fnx.bootstrap!))')
881
+ ```
882
+
883
+ Done. It will automatically inject all your dependencies according to your `.fnx.fnl` file, similar to using the `fnx` command.
884
+
885
+ To enforce the path for the `.fnx.fnl` file:
886
+
887
+ ```ruby
888
+ fennel.eval('(let [fnx (require :fnx)] (fnx.bootstrap! "/project/.fnx.fnl"))')
889
+ ```
890
+
786
891
  ## Global vs Isolated
787
892
 
788
893
  You can use the **global** helper that provides an _API_ and a _State_ for quick-and-dirty coding. It uses internally a Ruby [_Singleton_](https://docs.ruby-lang.org/en/3.1/Singleton.html):
@@ -821,8 +926,8 @@ You may want to use an isolated API for scenarios like interacting with two Lua
821
926
  ```ruby
822
927
  require 'sweet-moon'
823
928
 
824
- api_5 = SweetMoon.global.config(shared_object: '/usr/lib/liblua5.s')
825
- api_3 = SweetMoon.global.config(shared_object: '/usr/lib/liblua3.so')
929
+ api_5 = SweetMoon::API.new(shared_object: '/usr/lib/liblua5.s')
930
+ api_3 = SweetMoon::API.new(shared_object: '/usr/lib/liblua3.so')
826
931
 
827
932
  api_5.luaL_newstate
828
933
 
@@ -882,7 +987,7 @@ require 'sweet-moon'
882
987
 
883
988
  begin
884
989
  SweetMoon.global.state.eval('return 1 + true')
885
- rescue SweetMoon::Errors::LuaSyntaxError => error
990
+ rescue SweetMoon::Errors::LuaRuntimeError => error
886
991
  puts error.message
887
992
  # => [string "return 1 + true"]:1: attempt to perform arithmetic on a boolean value
888
993
  end
@@ -896,7 +1001,7 @@ require 'sweet-moon/errors'
896
1001
 
897
1002
  begin
898
1003
  SweetMoon.global.state.eval('return 1 + true')
899
- rescue LuaSyntaxError => error
1004
+ rescue LuaRuntimeError => error
900
1005
  puts error.message
901
1006
  # => [string "return 1 + true"]:1: attempt to perform arithmetic on a boolean value
902
1007
  end
@@ -904,9 +1009,9 @@ end
904
1009
 
905
1010
  ## Where can I find .so files?
906
1011
 
907
- Due to the Lua's popularity, you likely have it already on your system, and _Sweet Moon_ will be able to find the files on its own.
1012
+ 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.
908
1013
 
909
- Either way, you can download it from this page:
1014
+ Either way, you can download it from:
910
1015
  - [Lua Binaries](http://luabinaries.sourceforge.net)
911
1016
  - [LuaJIT releases](http://luajit.org/download.html)
912
1017
 
@@ -1138,6 +1243,26 @@ rubocop -a
1138
1243
  rspec
1139
1244
  ```
1140
1245
 
1246
+ ### Tests Setup
1247
+
1248
+ To setup tests:
1249
+
1250
+ ```
1251
+ cp config/tests.sample.yml config/tests.yml
1252
+ ```
1253
+
1254
+ Clone the [sweet-moon-test](https://github.com/gbaptista/sweet-moon-test) repo somewhere:
1255
+
1256
+ ```sh
1257
+ git clone git@github.com:gbaptista/sweet-moon-test.git
1258
+ ```
1259
+
1260
+ Update the [`config/tests.yml`](https://github.com/gbaptista/sweet-moon/blob/main/config/tests.sample.yml) accordingly.
1261
+
1262
+ Alternatively: Find or build the _Shared Objects_ for your Operating System on your own.
1263
+
1264
+ ### Running
1265
+
1141
1266
  ```sh
1142
1267
  ./ports/in/shell/sweet-moon version
1143
1268
 
@@ -1147,3 +1272,21 @@ bundle exec sweet-moon signatures /lua/lib/542 542.rb
1147
1272
 
1148
1273
  bundle exec ruby some/file.rb
1149
1274
  ```
1275
+
1276
+ ### Supporting New Versions
1277
+
1278
+ Download both the source code and the libraries.
1279
+
1280
+ Example: For [Lua 5.4.2](https://sourceforge.net/projects/luabinaries/files/5.4.2/), you would download _"Linux Libraries"_ and _"Docs and Sources."_
1281
+
1282
+ Extract everything to a folder, e.g., `lua-542-source-libs`.
1283
+
1284
+ Run the command to extract the signatures:
1285
+
1286
+ ```shell
1287
+ bundle exec sweet-moon signatures /home/me/lua-542-source-libs 542.rb
1288
+ ```
1289
+
1290
+ Check the `542.rb` file for the output and then start coding.
1291
+
1292
+ You can use the [`logic/signatures`](https://github.com/gbaptista/sweet-moon/tree/main/logic/signatures) folder as a reference starting point.
@@ -9,23 +9,26 @@ module Component
9
9
  Function = {
10
10
  push!: ->(api, state, closure) {
11
11
  handler = ->(current_state) {
12
- input = Reader[:read_all!].(api, current_state)
12
+ updated_state = state.merge(lua: current_state)
13
+ input = Reader[:read_all!].(api, updated_state)
13
14
  result = closure.(*input)
14
- Writer[:push!].(api, current_state, result)
15
+ Writer[:push!].(api, updated_state, result)
15
16
  return 1
16
17
  }
17
18
 
18
- api.lua_pushcclosure(state, handler, 0)
19
+ state[:avoid_gc] << handler
20
+
21
+ api.lua_pushcclosure(state[:lua], handler, 0)
19
22
  },
20
23
 
21
24
  read!: ->(api, state, _stack_index) {
22
25
  reference = api.luaL_ref(
23
- state, Logic::V50::Interpreter[:LUA_REGISTRYINDEX]
26
+ state[:lua], Logic::V50::Interpreter[:LUA_REGISTRYINDEX]
24
27
  )
25
28
 
26
29
  { value: ->(input = [], output = 1) {
27
30
  api.lua_rawgeti(
28
- state, Logic::V50::Interpreter[:LUA_REGISTRYINDEX], reference
31
+ state[:lua], Logic::V50::Interpreter[:LUA_REGISTRYINDEX], reference
29
32
  )
30
33
 
31
34
  input.each do |value|
@@ -11,34 +11,40 @@ module Component
11
11
 
12
12
  create_state!: ->(api) {
13
13
  state = api.lua_open
14
- { state: state, error: state ? nil : :MemoryAllocation }
14
+ { state: { lua: state, avoid_gc: [] },
15
+ error: state ? nil : :MemoryAllocation }
15
16
  },
16
17
 
17
18
  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)
19
+ api.luaopen_base(state[:lua])
20
+ api.luaopen_table(state[:lua])
21
+ api.luaopen_io(state[:lua])
22
+ api.luaopen_string(state[:lua])
23
+ api.luaopen_math(state[:lua])
23
24
 
24
- api.lua_settop(state, -7 - 1)
25
+ api.lua_settop(state[:lua], -7 - 1)
25
26
 
26
27
  { state: state }
27
28
  },
28
29
 
29
30
  load_file_and_push_chunck!: ->(api, state, path) {
30
- result = api.luaL_loadfile(state, path)
31
+ result = api.luaL_loadfile(state[:lua], path)
31
32
  { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
32
33
  },
33
34
 
34
35
  push_chunk!: ->(api, state, value) {
35
- result = api.luaL_loadbuffer(state, value, value.size, value)
36
+ result = api.luaL_loadbuffer(state[:lua], value, value.size, value)
36
37
 
37
38
  { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
38
39
  },
39
40
 
40
- set_table!: ->(api, state, variable, value) {
41
- Table[:set!].(api, state, variable, value)
41
+ set_table!: ->(api, state) {
42
+ result = api.lua_settable(state[:lua], -3)
43
+
44
+ api.lua_settop(state[:lua], -2)
45
+
46
+ { state: state,
47
+ error: Interpreter[:_error].(api, state, result, pull: false) }
42
48
  },
43
49
 
44
50
  push_value!: ->(api, state, value) {
@@ -47,31 +53,38 @@ module Component
47
53
  },
48
54
 
49
55
  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])
56
+ api.lua_pushstring(state[:lua], variable)
57
+ api.lua_insert(state[:lua], -2)
58
+ api.lua_settable(state[:lua], Logic::V50::Interpreter[:LUA_GLOBALSINDEX])
53
59
  { state: state }
54
60
  },
55
61
 
56
62
  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])
63
+ extra_pop = true
64
+ if variable == '_G'
65
+ variable = key
66
+ key = nil
67
+ extra_pop = false
68
+ end
69
+
70
+ api.lua_pushstring(state[:lua], variable.to_s)
71
+ api.lua_gettable(state[:lua], Logic::V50::Interpreter[:LUA_GLOBALSINDEX])
59
72
 
60
73
  Table[:read_field_and_push!].(api, state, key, -1) unless key.nil?
61
74
 
62
- { state: state }
75
+ { state: state, extra_pop: extra_pop }
63
76
  },
64
77
 
65
78
  call!: ->(api, state, inputs = 0, outputs = 1) {
66
- result = api.lua_pcall(state, inputs, outputs, 0)
79
+ result = api.lua_pcall(state[:lua], inputs, outputs, 0)
67
80
  { state: state, error: Interpreter[:_error].(api, state, result, pull: true) }
68
81
  },
69
82
 
70
83
  read_and_pop!: ->(api, state, stack_index = -1, extra_pop: false) {
71
84
  result = Component::V50::Reader[:read!].(api, state, stack_index)
72
85
 
73
- api.lua_settop(state, -2) if result[:pop]
74
- api.lua_settop(state, -2) if extra_pop
86
+ api.lua_settop(state[:lua], -2) if result[:pop]
87
+ api.lua_settop(state[:lua], -2) if extra_pop
75
88
 
76
89
  { state: state, output: result[:value] }
77
90
  },
@@ -83,9 +96,12 @@ module Component
83
96
  },
84
97
 
85
98
  destroy_state!: ->(api, state) {
86
- result = api.lua_close(state)
99
+ result = api.lua_close(state[:lua])
100
+
101
+ state.delete(:lua)
102
+ state.delete(:avoid_gc)
87
103
 
88
- { state: nil, error: Interpreter[:_error].(api, state, result) }
104
+ { state: nil, error: Interpreter[:_error].(api, nil, result) }
89
105
  },
90
106
 
91
107
  _error: ->(api, state, code, options = {}) {
@@ -94,7 +110,7 @@ module Component
94
110
  ] || :error
95
111
 
96
112
  if code.is_a?(Numeric) && code >= 1
97
- return { status: status } unless options[:pull]
113
+ return { status: status } unless options[:pull] && state
98
114
 
99
115
  { status: status,
100
116
  value: Interpreter[:read_and_pop!].(api, state, -1)[:output] }
@@ -8,15 +8,16 @@ module Component
8
8
  module V50
9
9
  Reader = {
10
10
  read_all!: ->(api, state) {
11
- (1..api.lua_gettop(state)).map do
11
+ (1..api.lua_gettop(state[:lua])).map do
12
12
  Interpreter[:read_and_pop!].(api, state)[:output]
13
13
  end.reverse
14
14
  },
15
15
 
16
16
  read!: ->(api, state, stack_index = -1) {
17
- stack_index = api.lua_gettop(state) if stack_index == -1
17
+ stack_index = api.lua_gettop(state[:lua]) if stack_index == -1
18
18
 
19
- type = api.lua_typename(state, api.lua_type(state, stack_index)).read_string
19
+ type = api.lua_typename(state[:lua],
20
+ api.lua_type(state[:lua], stack_index)).read_string
20
21
 
21
22
  case type
22
23
  when 'string'
@@ -36,29 +37,30 @@ module Component
36
37
  else
37
38
  # none nil boolean lightuserdata number
38
39
  # string table function userdata thread
39
- { value: "#{type}: 0x#{api.lua_topointer(state, stack_index).address}",
40
+ { value:
41
+ "#{type}: 0x#{api.lua_topointer(state[:lua], stack_index).address}",
40
42
  type: type, pop: true }
41
43
  end
42
44
  },
43
45
 
44
46
  read_string!: ->(api, state, stack_index) {
45
- { value: api.lua_tostring(state, stack_index).read_string,
47
+ { value: api.lua_tostring(state[:lua], stack_index).read_string,
46
48
  pop: true }
47
49
  },
48
50
 
49
51
  read_number!: ->(api, state, stack_index) {
50
52
  if api.respond_to?(:lua_isinteger) &&
51
53
  api.respond_to?(:lua_tointeger) &&
52
- api.lua_isinteger(state, stack_index) == 1
54
+ api.lua_isinteger(state[:lua], stack_index) == 1
53
55
 
54
- return { value: api.lua_tointeger(state, stack_index), pop: true }
56
+ return { value: api.lua_tointeger(state[:lua], stack_index), pop: true }
55
57
  end
56
58
 
57
- { value: api.lua_tonumber(state, stack_index), pop: true }
59
+ { value: api.lua_tonumber(state[:lua], stack_index), pop: true }
58
60
  },
59
61
 
60
62
  read_boolean!: ->(api, state, stack_index) {
61
- { value: api.lua_toboolean(state, stack_index) == 1, pop: true }
63
+ { value: api.lua_toboolean(state[:lua], stack_index) == 1, pop: true }
62
64
  }
63
65
  }
64
66
  end
@@ -7,68 +7,70 @@ module Component
7
7
  module V50
8
8
  Table = {
9
9
  push!: ->(api, state, list, stack_index = -1) {
10
- stack_index = api.lua_gettop(state) if stack_index == -1
10
+ stack_index = api.lua_gettop(state[:lua]) if stack_index == -1
11
11
 
12
- api.lua_newtable(state)
12
+ api.lua_newtable(state[:lua])
13
13
 
14
14
  if list.is_a? Hash
15
15
  list.each_key do |key|
16
16
  Writer[:push!].(api, state, key)
17
17
  Writer[:push!].(api, state, list[key])
18
- api.lua_settable(state, stack_index + 1)
18
+ api.lua_settable(state[:lua], stack_index + 1)
19
19
  end
20
20
  else
21
21
  list.each_with_index do |value, index|
22
22
  Writer[:push!].(api, state, index + 1)
23
23
  Writer[:push!].(api, state, value)
24
- api.lua_settable(state, stack_index + 1)
24
+ api.lua_settable(state[:lua], stack_index + 1)
25
25
  end
26
26
  end
27
27
  },
28
28
 
29
29
  read!: ->(api, state, stack_index) {
30
- stack_index = api.lua_gettop(state) if stack_index == -1
30
+ stack_index = api.lua_gettop(state[:lua]) if stack_index == -1
31
31
 
32
- type = api.lua_typename(state, api.lua_type(state, stack_index)).read_string
32
+ type = api.lua_typename(state[:lua],
33
+ api.lua_type(state[:lua], stack_index)).read_string
33
34
 
34
- api.lua_pushnil(state)
35
+ api.lua_pushnil(state[:lua])
35
36
 
36
37
  return nil if type != 'table'
37
38
 
38
39
  tuples = []
39
40
 
40
- while api.lua_next(state, stack_index).positive?
41
+ while api.lua_next(state[:lua], stack_index).positive?
41
42
  value = Reader[:read!].(api, state, stack_index + 2)
42
43
  key = Reader[:read!].(api, state, stack_index + 1)
43
- api.lua_settop(state, -2) if value[:pop]
44
+ api.lua_settop(state[:lua], -2) if value[:pop]
44
45
 
45
46
  tuples << [key[:value], value[:value]]
46
47
 
47
- break if value[:type] == 'no value'
48
+ break if value[:type] == 'no value' || key[:value].instance_of?(Proc)
48
49
  end
49
50
 
50
51
  { value: Logic::Tables[:to_hash_or_array].(tuples), pop: true }
51
52
  },
52
53
 
53
54
  read_field_and_push!: ->(api, state, expected_key, stack_index) {
54
- stack_index = api.lua_gettop(state) if stack_index == -1
55
+ stack_index = api.lua_gettop(state[:lua]) if stack_index == -1
55
56
 
56
- type = api.lua_typename(state, api.lua_type(state, stack_index)).read_string
57
+ type = api.lua_typename(state[:lua],
58
+ api.lua_type(state[:lua], stack_index)).read_string
57
59
 
58
- api.lua_pushnil(state)
60
+ api.lua_pushnil(state[:lua])
59
61
 
60
62
  return nil if type != 'table'
61
63
 
62
64
  result = nil
63
65
 
64
- while api.lua_next(state, stack_index).positive?
66
+ while api.lua_next(state[:lua], stack_index).positive?
65
67
  value = Reader[:read!].(api, state, stack_index + 2)
66
68
  key = Reader[:read!].(api, state, stack_index + 1)
67
69
 
68
- api.lua_settop(state, -2) if value[:pop]
70
+ api.lua_settop(state[:lua], -2) if value[:pop]
69
71
 
70
72
  key_type = api.lua_typename(
71
- state, api.lua_type(state, stack_index + 1)
73
+ state[:lua], api.lua_type(state[:lua], stack_index + 1)
72
74
  ).read_string
73
75
 
74
76
  if Table[:is_same_key].(key_type, key[:value], expected_key)
@@ -76,10 +78,10 @@ module Component
76
78
  break
77
79
  end
78
80
 
79
- break if value[:type] == 'no value'
81
+ break if value[:type] == 'no value' || key[:value].instance_of?(Proc)
80
82
  end
81
83
 
82
- api.lua_settop(state, -2)
84
+ api.lua_settop(state[:lua], -2)
83
85
 
84
86
  Writer[:push!].(api, state, result)
85
87
  },
@@ -7,26 +7,26 @@ module Component
7
7
  push!: ->(api, state, value) {
8
8
  case Writer[:_to_lua_type].(value)
9
9
  when 'string'
10
- api.lua_pushstring(state, value.to_s)
10
+ api.lua_pushstring(state[:lua], value.to_s)
11
11
  when 'number'
12
- api.lua_pushnumber(state, value)
12
+ api.lua_pushnumber(state[:lua], value)
13
13
  when 'integer'
14
14
  if api.respond_to? :lua_pushinteger
15
- api.lua_pushinteger(state, value)
15
+ api.lua_pushinteger(state[:lua], value)
16
16
  else
17
- api.lua_pushnumber(state, value)
17
+ api.lua_pushnumber(state[:lua], value)
18
18
  end
19
19
  when 'nil'
20
- api.lua_pushnil(state)
20
+ api.lua_pushnil(state[:lua])
21
21
  when 'boolean'
22
- api.lua_pushboolean(state, value ? 1 : 0)
22
+ api.lua_pushboolean(state[:lua], value ? 1 : 0)
23
23
  when 'table'
24
24
  Table[:push!].(api, state, value)
25
25
  when 'function'
26
26
  Function[:push!].(api, state, value)
27
27
  else
28
28
  api.lua_pushstring(
29
- state, "#<#{value.class}:0x#{format('%016x', value.object_id)}>"
29
+ state[:lua], "#<#{value.class}:0x#{format('%016x', value.object_id)}>"
30
30
  )
31
31
  end
32
32
  },