sweet-moon 0.0.4 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
},
|