sweet-moon 0.0.4 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/README.md +278 -13
- data/components/api.rb +6 -3
- data/components/default.rb +17 -0
- data/components/injections/injections_503.rb +2 -1
- data/components/injections/injections_514.rb +2 -1
- data/components/injections/injections_542.rb +2 -1
- data/components/interpreters/50/function.rb +14 -50
- data/components/interpreters/50/interpreter.rb +12 -6
- data/components/interpreters/50/reader.rb +2 -62
- data/components/interpreters/50/table.rb +11 -48
- data/components/interpreters/50/writer.rb +2 -40
- data/components/interpreters/51/function.rb +3 -49
- data/components/interpreters/51/interpreter.rb +8 -7
- data/components/interpreters/51/reader.rb +2 -62
- data/components/interpreters/51/table.rb +2 -56
- data/components/interpreters/51/writer.rb +2 -40
- data/components/interpreters/54/function.rb +80 -24
- data/components/interpreters/54/interpreter.rb +9 -6
- data/components/interpreters/54/reader.rb +11 -10
- data/components/interpreters/54/table.rb +17 -12
- data/components/interpreters/54/writer.rb +4 -4
- data/config/tests.sample.yml +9 -8
- data/controllers/api.rb +4 -1
- data/controllers/state.rb +13 -3
- data/dsl/api.rb +23 -3
- data/dsl/cache.rb +90 -76
- data/dsl/errors.rb +9 -1
- data/dsl/fennel.rb +9 -6
- data/dsl/global.rb +26 -27
- data/dsl/state.rb +49 -9
- data/dsl/sweet_moon.rb +4 -4
- data/logic/spec.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 880cceae5913b9a748b5b318bfc27c56ccf58d7ae54b7f31f8aeea943c524aac
|
4
|
+
data.tar.gz: ab2abc87ef9ead4ea7be474963a92ad647326ec6d4ad1bfec62ed20d103d4e4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b613dba97c24527e3e71a8bd7c6d14cd98edcd9a0083a85463a3300f05886a81da33ea5c515108fe523ed43ab012760954edd40dacec4aa38a250e6846b3906
|
7
|
+
data.tar.gz: c8c09f0f1bc7cde58c789975b84491399af843b8d95cb69bd3600dbb4c22a056f232e99eea50d3af969ebea6fa298bd86214a596d7ab67afe5c4a209d8a43fa3
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -28,10 +28,14 @@ _Sweet Moon_ is a resilient solution that makes working with [Lua](https://www.l
|
|
28
28
|
- [Fennel](#fennel)
|
29
29
|
- [Fennel Usage](#fennel-usage)
|
30
30
|
- [Fennel Global vs Local Variables](#fennel-global-vs-local-variables)
|
31
|
+
- [allowedGlobals and options](#allowedglobals-and-options)
|
31
32
|
- [Fennel Setup](#fennel-setup)
|
32
33
|
- [Integration with fnx](#integration-with-fnx)
|
34
|
+
- [Fennel REPL](#fennel-repl)
|
33
35
|
- [Global vs Isolated](#global-vs-isolated)
|
36
|
+
- [Global FFI](#global-ffi)
|
34
37
|
- [Error Handling](#error-handling)
|
38
|
+
- [Ruby feat. Lua Errors](#ruby-feat-lua-errors)
|
35
39
|
- [Where can I find .so files?](#where-can-i-find-so-files)
|
36
40
|
- [Low-Level C API](#low-level-c-api)
|
37
41
|
- [The API](#the-api)
|
@@ -71,7 +75,7 @@ gem install sweet-moon
|
|
71
75
|
> **Disclaimer:** It's an early-stage project, and you should expect breaking changes.
|
72
76
|
|
73
77
|
```ruby
|
74
|
-
gem 'sweet-moon', '~> 0.0.
|
78
|
+
gem 'sweet-moon', '~> 0.0.7'
|
75
79
|
```
|
76
80
|
|
77
81
|
```ruby
|
@@ -442,6 +446,16 @@ second = state.get(:second)
|
|
442
446
|
second.([%w[a b c]]) # => 'b'
|
443
447
|
```
|
444
448
|
|
449
|
+
Alternatively, you can send the `outputs` parameter:
|
450
|
+
|
451
|
+
```ruby
|
452
|
+
require 'sweet-moon'
|
453
|
+
|
454
|
+
state = SweetMoon::State.new
|
455
|
+
|
456
|
+
state.eval('return "a", "b"', { outputs: 2 }) # => ['a', 'b']
|
457
|
+
```
|
458
|
+
|
445
459
|
You can call Ruby _Lambdas_ from _Lua_ as well:
|
446
460
|
|
447
461
|
```ruby
|
@@ -612,21 +626,21 @@ state.add_package_path('/home/me/my-lua-modules/?/init.lua')
|
|
612
626
|
|
613
627
|
state.add_package_cpath('/home/me/my-lua-modules/?.so')
|
614
628
|
|
615
|
-
state.add_package_path('/home/me/fennel
|
629
|
+
state.add_package_path('/home/me/fennel/?.lua')
|
616
630
|
|
617
|
-
state.add_package_cpath('/home/me
|
631
|
+
state.add_package_cpath('/home/me/?.so')
|
618
632
|
|
619
633
|
state.package_path
|
620
634
|
# => ['./?.lua',
|
621
635
|
# './?/init.lua',
|
622
636
|
# '/home/me/my-lua-modules/?.lua',
|
623
637
|
# '/home/me/my-lua-modules/?/init.lua',
|
624
|
-
# '/home/me/fennel
|
638
|
+
# '/home/me/fennel/?.lua']
|
625
639
|
|
626
640
|
state.package_cpath
|
627
641
|
# => ['./?.so',
|
628
642
|
# '/home/me/my-lua-modules/?.so',
|
629
|
-
# '/home/me
|
643
|
+
# '/home/me/?.so']
|
630
644
|
```
|
631
645
|
|
632
646
|
Requiring a module:
|
@@ -646,8 +660,8 @@ You can set packages in State constructors:
|
|
646
660
|
require 'sweet-moon'
|
647
661
|
|
648
662
|
SweetMoon::State.new(
|
649
|
-
package_path: '/folder/lib
|
650
|
-
package_cpath: '/lib/lib
|
663
|
+
package_path: '/folder/lib/?.lua',
|
664
|
+
package_cpath: '/lib/lib/?.so',
|
651
665
|
)
|
652
666
|
```
|
653
667
|
|
@@ -657,8 +671,8 @@ Also, you can add packages through the global config:
|
|
657
671
|
require 'sweet-moon'
|
658
672
|
|
659
673
|
SweetMoon.global.config(
|
660
|
-
package_path: '/folder/lib
|
661
|
-
package_cpath: '/lib/lib
|
674
|
+
package_path: '/folder/lib/?.lua',
|
675
|
+
package_cpath: '/lib/lib/?.so',
|
662
676
|
)
|
663
677
|
```
|
664
678
|
|
@@ -818,6 +832,71 @@ fennel.eval('var-b') # => nil
|
|
818
832
|
fennel.eval('_G.var-b') # => 35
|
819
833
|
```
|
820
834
|
|
835
|
+
### allowedGlobals and options
|
836
|
+
|
837
|
+
As Lua, Fennel functions may return [multiple results](https://www.lua.org/pil/5.1.html), so `eval` and `load` accept a second parameter to indicate the expected number of outputs:
|
838
|
+
|
839
|
+
```fnl
|
840
|
+
; source.fnl
|
841
|
+
|
842
|
+
(fn multi [] (values "c" "d"))
|
843
|
+
|
844
|
+
(multi)
|
845
|
+
```
|
846
|
+
|
847
|
+
```ruby
|
848
|
+
require 'sweet-moon'
|
849
|
+
|
850
|
+
fennel = SweetMoon::State.new.fennel
|
851
|
+
|
852
|
+
fennel.eval('(values "a" "b")', 2) # => ['a', 'b']
|
853
|
+
fennel.load('source.fnl', 2) # => ['c', 'd']
|
854
|
+
```
|
855
|
+
|
856
|
+
The Fennel API offers [some options](https://fennel-lang.org/api) that `eval` and `load` accept as a third parameter:
|
857
|
+
|
858
|
+
```ruby
|
859
|
+
require 'sweet-moon'
|
860
|
+
|
861
|
+
fennel = SweetMoon::State.new.fennel
|
862
|
+
|
863
|
+
fennel.eval('(print (+ 2 3))', 1, { allowedGlobals: ['print'] }) # => 5
|
864
|
+
|
865
|
+
fennel.eval('(print (+ 2 3))', 1, { allowedGlobals: [] })
|
866
|
+
# Compile error in unknown:1 (SweetMoon::Errors::LuaRuntimeError)
|
867
|
+
# unknown identifier in strict mode: print
|
868
|
+
|
869
|
+
# (print (+ 2 3))
|
870
|
+
# ^^^^^
|
871
|
+
# * Try looking to see if there's a typo.
|
872
|
+
# * Try using the _G table instead, eg. _G.print if you really want a global.
|
873
|
+
# * Try moving this code to somewhere that print is in scope.
|
874
|
+
# * Try binding print as a local in the scope of this code.
|
875
|
+
```
|
876
|
+
|
877
|
+
Alternatively, you can use the second parameter for options as well:
|
878
|
+
|
879
|
+
```ruby
|
880
|
+
require 'sweet-moon'
|
881
|
+
|
882
|
+
fennel = SweetMoon::State.new.fennel
|
883
|
+
|
884
|
+
fennel.eval('(print (+ 2 3))', { allowedGlobals: ['print'] }) # => 5
|
885
|
+
```
|
886
|
+
|
887
|
+
You can also specify the expected outputs in the options parameter (it will be removed and not forwarded to Fennel):
|
888
|
+
|
889
|
+
```ruby
|
890
|
+
require 'sweet-moon'
|
891
|
+
|
892
|
+
fennel = SweetMoon::State.new.fennel
|
893
|
+
|
894
|
+
fennel.eval(
|
895
|
+
'(values "a" "b")',
|
896
|
+
{ allowedGlobals: ['values'], outputs: 2 }
|
897
|
+
) # => ['a', 'b']
|
898
|
+
```
|
899
|
+
|
821
900
|
### Fennel Setup
|
822
901
|
|
823
902
|
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.
|
@@ -831,7 +910,7 @@ require 'sweet-moon'
|
|
831
910
|
|
832
911
|
state = SweetMoon::State.new
|
833
912
|
|
834
|
-
state.add_package_path('/folder/fennel
|
913
|
+
state.add_package_path('/folder/fennel/?.lua')
|
835
914
|
|
836
915
|
state.fennel.eval('(+ 1 1)') # => 2
|
837
916
|
```
|
@@ -841,7 +920,7 @@ With the constructor:
|
|
841
920
|
```ruby
|
842
921
|
require 'sweet-moon'
|
843
922
|
|
844
|
-
fennel = SweetMoon::State.new(package_path: '/folder/fennel
|
923
|
+
fennel = SweetMoon::State.new(package_path: '/folder/fennel/?.lua').fennel
|
845
924
|
|
846
925
|
fennel.eval('(+ 1 1)') # => 2
|
847
926
|
```
|
@@ -851,7 +930,7 @@ With global:
|
|
851
930
|
```ruby
|
852
931
|
require 'sweet-moon'
|
853
932
|
|
854
|
-
SweetMoon.global.state.add_package_path('/folder/fennel
|
933
|
+
SweetMoon.global.state.add_package_path('/folder/fennel/?.lua')
|
855
934
|
|
856
935
|
SweetMoon.global.state.fennel.eval('(+ 1 1)') # => 2
|
857
936
|
```
|
@@ -861,7 +940,7 @@ Alternatively:
|
|
861
940
|
```ruby
|
862
941
|
require 'sweet-moon'
|
863
942
|
|
864
|
-
SweetMoon.global.config(package_path: '/folder/fennel
|
943
|
+
SweetMoon.global.config(package_path: '/folder/fennel/?.lua')
|
865
944
|
|
866
945
|
SweetMoon.global.state.fennel.eval('(+ 1 1)') # => 2
|
867
946
|
```
|
@@ -888,6 +967,44 @@ To enforce the path for the `.fnx.fnl` file:
|
|
888
967
|
fennel.eval('(let [fnx (require :fnx)] (fnx.bootstrap! "/project/.fnx.fnl"))')
|
889
968
|
```
|
890
969
|
|
970
|
+
### Fennel REPL
|
971
|
+
|
972
|
+
In Ruby, you can start a [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) at any time somewhere in your code with [_pry_](https://github.com/pry/pry):
|
973
|
+
|
974
|
+
```ruby
|
975
|
+
require 'pry'
|
976
|
+
|
977
|
+
binding.pry
|
978
|
+
```
|
979
|
+
|
980
|
+
The same is true for Fennel, you just need to:
|
981
|
+
```fnl
|
982
|
+
(let [fennel (require :fennel)]
|
983
|
+
(fennel.repl {}))
|
984
|
+
```
|
985
|
+
|
986
|
+
Fennel's REPL won't have your _local_ values. But, you can tweak it to receive values to be checked inside the REPL:
|
987
|
+
|
988
|
+
```fnl
|
989
|
+
(fn my-repl [to-expose]
|
990
|
+
(let [fennel (require :fennel) env _G]
|
991
|
+
(each [key value (pairs to-expose)] (tset env key value))
|
992
|
+
(fennel.repl {:env env})))
|
993
|
+
|
994
|
+
(local value "some value")
|
995
|
+
|
996
|
+
(my-repl {:value value})
|
997
|
+
|
998
|
+
; Inside the REPL:
|
999
|
+
|
1000
|
+
; >> value
|
1001
|
+
; "some value"
|
1002
|
+
```
|
1003
|
+
|
1004
|
+
You can install [_readline_](https://luarocks.org/modules/peterbillam/readline) for a better experience, e.g., autocompleting.
|
1005
|
+
|
1006
|
+
> _Check [Fennel's documentation](https://fennel-lang.org/api#start-a-configurable-repl) to learn more about the REPL._
|
1007
|
+
|
891
1008
|
## Global vs Isolated
|
892
1009
|
|
893
1010
|
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):
|
@@ -934,6 +1051,8 @@ api_5.luaL_newstate
|
|
934
1051
|
api_3.luaH_new
|
935
1052
|
```
|
936
1053
|
|
1054
|
+
> _Check the caveats related to [_Global FFI_](#global-ffi) when working with multiple versions._
|
1055
|
+
|
937
1056
|
On the other hand, using the **global** _State_ may lead to a lot of issues. You need to consider from simple things – _"If I load two different files, the first file may impact the state of the second one?"_ – to more complex ones like multithreading, concurrency, etc.
|
938
1057
|
|
939
1058
|
So, you can at any time create a new isolated _State_ and destroy it when you don't need it anymore:
|
@@ -963,6 +1082,48 @@ state_5.eval('return _VERSION') # => Lua 5.4
|
|
963
1082
|
state_3.eval('return _VERSION') # => Lua 3.2
|
964
1083
|
```
|
965
1084
|
|
1085
|
+
> _Check the caveats related to [_Global FFI_](#global-ffi) when working with multiple versions._
|
1086
|
+
|
1087
|
+
## Global FFI
|
1088
|
+
|
1089
|
+
Some Lua libraries (e.g., [_readline_](https://pjb.com.au/comp/lua/readline.html) and [_luafilesystem_](https://keplerproject.github.io/luafilesystem/)) require the Lua C API functions available in the global C environment.
|
1090
|
+
|
1091
|
+
By default, _Sweet Moon_ enables [_Global FFI_](https://github.com/ffi/ffi/wiki/Loading-Libraries#function-visibility) to reduce friction when using popular libraries.
|
1092
|
+
|
1093
|
+
Using distinct Lua versions simultaneously with multiple _Shared Objects_ may be dangerous in this setup: Two APIs with the same name functions could be an issue because something will be overwritten.
|
1094
|
+
|
1095
|
+
Also, libraries that need Lua C API functions are compiled for a specific Lua version. If you are, e.g., using _LuaJIT_ and your library expects the _Standard Lua_, you may face issues.
|
1096
|
+
|
1097
|
+
You can disable _Global FFI_ at any time with:
|
1098
|
+
|
1099
|
+
```ruby
|
1100
|
+
require 'sweet-moon'
|
1101
|
+
|
1102
|
+
SweetMoon.global.config(global_ffi: false)
|
1103
|
+
|
1104
|
+
SweetMoon::State.new(global_ffi: false)
|
1105
|
+
|
1106
|
+
SweetMoon::API.new(global_ffi: false)
|
1107
|
+
```
|
1108
|
+
|
1109
|
+
To check if it's enabled or not:
|
1110
|
+
|
1111
|
+
```ruby
|
1112
|
+
require 'sweet-moon'
|
1113
|
+
|
1114
|
+
SweetMoon.global.api.meta.global_ffi # => true
|
1115
|
+
SweetMoon.global.state.meta.global_ffi # => true
|
1116
|
+
|
1117
|
+
SweetMoon::API.new.meta.global_ffi # => true
|
1118
|
+
|
1119
|
+
SweetMoon::State.new.meta.global_ffi # => true
|
1120
|
+
```
|
1121
|
+
|
1122
|
+
**Caveats:**
|
1123
|
+
|
1124
|
+
Binding globally a C API is irreversible, so if you start something with `global_ffi: true` and then change to `global_ffi: false`, it won't make the global one disappear. If you need _local_, ensure that you do it from the first line and never put anything as global throughout the entire program life cycle.
|
1125
|
+
|
1126
|
+
Also, the simple action of accessing `meta.global_ff` will bind the API, so you need to set your desired configuration before checking.
|
966
1127
|
|
967
1128
|
## Error Handling
|
968
1129
|
|
@@ -1007,6 +1168,108 @@ rescue LuaRuntimeError => error
|
|
1007
1168
|
end
|
1008
1169
|
```
|
1009
1170
|
|
1171
|
+
### Ruby feat. Lua Errors
|
1172
|
+
|
1173
|
+
Lua errors can be rescued inside Ruby:
|
1174
|
+
|
1175
|
+
```lua
|
1176
|
+
-- source.lua
|
1177
|
+
error('error from lua')
|
1178
|
+
```
|
1179
|
+
|
1180
|
+
```ruby
|
1181
|
+
require 'sweet-moon'
|
1182
|
+
require 'sweet-moon/errors'
|
1183
|
+
|
1184
|
+
state = SweetMoon::State.new
|
1185
|
+
|
1186
|
+
begin
|
1187
|
+
state.load('source.lua')
|
1188
|
+
rescue LuaRuntimeError => e
|
1189
|
+
puts e.message
|
1190
|
+
# => source.lua:2: error from lua
|
1191
|
+
end
|
1192
|
+
```
|
1193
|
+
|
1194
|
+
Ruby errors can be handled inside Lua:
|
1195
|
+
|
1196
|
+
```ruby
|
1197
|
+
require 'sweet-moon'
|
1198
|
+
|
1199
|
+
state = SweetMoon::State.new
|
1200
|
+
|
1201
|
+
state.set(:rubyFn, -> { raise 'error from ruby' })
|
1202
|
+
|
1203
|
+
state.load('source.lua')
|
1204
|
+
```
|
1205
|
+
|
1206
|
+
```lua
|
1207
|
+
-- source.lua
|
1208
|
+
local status, err = pcall(rubyFn)
|
1209
|
+
|
1210
|
+
print(status) -- => false
|
1211
|
+
|
1212
|
+
print(err)
|
1213
|
+
-- [string " return function (...)..."]:5: RuntimeError: error from ruby stack traceback:
|
1214
|
+
-- [string " return function (...)..."]:5: in function 'rubyFn'
|
1215
|
+
-- [C]: in function 'pcall'
|
1216
|
+
-- source.lua:2: in main chunk
|
1217
|
+
```
|
1218
|
+
|
1219
|
+
Ruby errors not handled inside Lua can be rescued inside Ruby again, with an additional Lua backtrace:
|
1220
|
+
|
1221
|
+
```lua
|
1222
|
+
-- source.lua
|
1223
|
+
a = 1
|
1224
|
+
|
1225
|
+
rubyFn()
|
1226
|
+
```
|
1227
|
+
|
1228
|
+
```ruby
|
1229
|
+
require 'sweet-moon'
|
1230
|
+
|
1231
|
+
state = SweetMoon::State.new
|
1232
|
+
|
1233
|
+
state.set(:rubyFn, -> { raise 'error from ruby' })
|
1234
|
+
|
1235
|
+
begin
|
1236
|
+
state.load('source.lua')
|
1237
|
+
rescue RuntimeError => e
|
1238
|
+
puts e.message # => error from ruby
|
1239
|
+
|
1240
|
+
puts e.backtrace.last
|
1241
|
+
# => source.lua:4: in main chunk
|
1242
|
+
end
|
1243
|
+
```
|
1244
|
+
|
1245
|
+
Lua errors inside Lua functions can be rescued inside Ruby:
|
1246
|
+
|
1247
|
+
```lua
|
1248
|
+
-- source.lua
|
1249
|
+
function luaFn()
|
1250
|
+
error('lua function error')
|
1251
|
+
end
|
1252
|
+
```
|
1253
|
+
|
1254
|
+
```ruby
|
1255
|
+
require 'sweet-moon'
|
1256
|
+
require 'sweet-moon/errors'
|
1257
|
+
|
1258
|
+
state = SweetMoon::State.new
|
1259
|
+
|
1260
|
+
state.load('source.lua')
|
1261
|
+
|
1262
|
+
lua_fn = state.get(:luaFn)
|
1263
|
+
|
1264
|
+
begin
|
1265
|
+
lua_fn.()
|
1266
|
+
rescue LuaRuntimeError => e
|
1267
|
+
puts e.message # => "source.lua:3: lua function error"
|
1268
|
+
end
|
1269
|
+
```
|
1270
|
+
|
1271
|
+
For Fennel, all the examples above are equally true, with additional stack traceback as well.
|
1272
|
+
|
1010
1273
|
## Where can I find .so files?
|
1011
1274
|
|
1012
1275
|
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.
|
@@ -1261,6 +1524,8 @@ Update the [`config/tests.yml`](https://github.com/gbaptista/sweet-moon/blob/mai
|
|
1261
1524
|
|
1262
1525
|
Alternatively: Find or build the _Shared Objects_ for your Operating System on your own.
|
1263
1526
|
|
1527
|
+
Install the expected Lua _rocks_ described in `config/tests.yml`.
|
1528
|
+
|
1264
1529
|
### Running
|
1265
1530
|
|
1266
1531
|
```sh
|
data/components/api.rb
CHANGED
@@ -2,7 +2,7 @@ require 'ffi'
|
|
2
2
|
|
3
3
|
module Component
|
4
4
|
API = {
|
5
|
-
open!: ->(shared_objects) {
|
5
|
+
open!: ->(shared_objects, options = {}, default = {}) {
|
6
6
|
api = Module.new
|
7
7
|
|
8
8
|
api.extend FFI::Library
|
@@ -10,8 +10,11 @@ module Component
|
|
10
10
|
# TODO: Lua Constants
|
11
11
|
# attach_variable
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
global_ffi = default[:global_ffi]
|
14
|
+
|
15
|
+
global_ffi = options[:global_ffi] unless options[:global_ffi].nil?
|
16
|
+
|
17
|
+
if global_ffi
|
15
18
|
api.ffi_lib_flags(:global, :now)
|
16
19
|
else
|
17
20
|
api.ffi_lib_flags(:local, :now)
|
@@ -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,55 +1,19 @@
|
|
1
|
-
require_relative '
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
},
|
23
|
-
|
24
|
-
read!: ->(api, state, _stack_index) {
|
25
|
-
reference = api.luaL_ref(
|
26
|
-
state[:lua], Logic::V50::Interpreter[:LUA_REGISTRYINDEX]
|
27
|
-
)
|
28
|
-
|
29
|
-
{ value: ->(input = [], output = 1) {
|
30
|
-
api.lua_rawgeti(
|
31
|
-
state[:lua], Logic::V50::Interpreter[:LUA_REGISTRYINDEX], reference
|
32
|
-
)
|
33
|
-
|
34
|
-
input.each do |value|
|
35
|
-
Writer[:push!].(api, state, value)
|
36
|
-
end
|
37
|
-
|
38
|
-
result = Interpreter[:call!].(api, state, input.size, output)
|
39
|
-
|
40
|
-
if result[:error]
|
41
|
-
raise SweetMoon::Errors::SweetMoonErrorHelper.for(
|
42
|
-
result[:error][:status]
|
43
|
-
), result[:error][:value]
|
44
|
-
end
|
45
|
-
|
46
|
-
result = Reader[:read_all!].(api, state)
|
47
|
-
|
48
|
-
return result.first if output == 1
|
49
|
-
|
50
|
-
result
|
51
|
-
}, pop: false }
|
52
|
-
}
|
53
|
-
}
|
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
|
54
18
|
end
|
55
19
|
end
|
@@ -1,17 +1,19 @@
|
|
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: { lua: state, avoid_gc: [] },
|
16
|
+
{ state: { lua: state, avoid_gc: [], ruby_error_info: nil },
|
15
17
|
error: state ? nil : :MemoryAllocation }
|
16
18
|
},
|
17
19
|
|
@@ -48,7 +50,7 @@ module Component
|
|
48
50
|
},
|
49
51
|
|
50
52
|
push_value!: ->(api, state, value) {
|
51
|
-
Writer[:push!].(api, state, value)
|
53
|
+
Writer[:push!].(api, state, Component::V50, value)
|
52
54
|
{ state: state }
|
53
55
|
},
|
54
56
|
|
@@ -70,7 +72,10 @@ module Component
|
|
70
72
|
api.lua_pushstring(state[:lua], variable.to_s)
|
71
73
|
api.lua_gettable(state[:lua], Logic::V50::Interpreter[:LUA_GLOBALSINDEX])
|
72
74
|
|
73
|
-
|
75
|
+
unless key.nil?
|
76
|
+
Table[:read_field_and_push!].(api, state, Component::V50, key,
|
77
|
+
-1)
|
78
|
+
end
|
74
79
|
|
75
80
|
{ state: state, extra_pop: extra_pop }
|
76
81
|
},
|
@@ -81,7 +86,8 @@ module Component
|
|
81
86
|
},
|
82
87
|
|
83
88
|
read_and_pop!: ->(api, state, stack_index = -1, extra_pop: false) {
|
84
|
-
result = Component::V50::Reader[:read!].(api, state,
|
89
|
+
result = Component::V50::Reader[:read!].(api, state, Component::V50,
|
90
|
+
stack_index)
|
85
91
|
|
86
92
|
api.lua_settop(state[:lua], -2) if result[:pop]
|
87
93
|
api.lua_settop(state[:lua], -2) if extra_pop
|
@@ -90,7 +96,7 @@ module Component
|
|
90
96
|
},
|
91
97
|
|
92
98
|
read_all!: ->(api, state) {
|
93
|
-
result = Reader[:read_all!].(api, state)
|
99
|
+
result = Reader[:read_all!].(api, state, Component::V50)
|
94
100
|
|
95
101
|
{ state: state, output: result }
|
96
102
|
},
|