sweet-moon 0.0.3 → 0.0.6
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 +283 -16
- 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 +27 -9
- data/components/interpreters/50/reader.rb +2 -62
- data/components/interpreters/50/table.rb +12 -49
- data/components/interpreters/50/writer.rb +2 -40
- data/components/interpreters/51/function.rb +3 -49
- data/components/interpreters/51/interpreter.rb +16 -10
- 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 +17 -9
- 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 +10 -7
- data/controllers/api.rb +4 -1
- data/controllers/state.rb +47 -12
- data/dsl/api.rb +23 -3
- data/dsl/cache.rb +90 -76
- data/dsl/errors.rb +9 -1
- data/dsl/fennel.rb +2 -0
- data/dsl/global.rb +26 -27
- data/dsl/state.rb +26 -7
- data/dsl/sweet_moon.rb +4 -4
- data/logic/interpreters/interpreter_50.rb +1 -0
- data/logic/interpreters/interpreter_54.rb +5 -5
- 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: 46891cd3e8103176f3f909415432df155df1bd33cbed89a80f0042f5d303a2b7
|
4
|
+
data.tar.gz: af7617e43eacc588135285dbd652f644d9bda8b87735c86ff89a7719ce6bfe1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1949e5f83c00dd65cdf78e2e8ebd4f66654dc24df1769add99ad8f01e75cc97bcb090e9d0dc0cf5d10dcdd4d1d338252b4ad78894bd3d4cef40b91ae31aab3d0
|
7
|
+
data.tar.gz: 9a09f1231c7e02250f232e368abd95b7bb1b4d5e366ef2614ce9871248c49201fb480b8b698833df66d769e7688602e8c3415a454366ef5ad3ede02163e1c5a4
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -21,15 +21,20 @@ _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)
|
33
|
+
- [Fennel REPL](#fennel-repl)
|
31
34
|
- [Global vs Isolated](#global-vs-isolated)
|
35
|
+
- [Global FFI](#global-ffi)
|
32
36
|
- [Error Handling](#error-handling)
|
37
|
+
- [Ruby feat. Lua Errors](#ruby-feat-lua-errors)
|
33
38
|
- [Where can I find .so files?](#where-can-i-find-so-files)
|
34
39
|
- [Low-Level C API](#low-level-c-api)
|
35
40
|
- [The API](#the-api)
|
@@ -69,7 +74,7 @@ gem install sweet-moon
|
|
69
74
|
> **Disclaimer:** It's an early-stage project, and you should expect breaking changes.
|
70
75
|
|
71
76
|
```ruby
|
72
|
-
gem 'sweet-moon', '~> 0.0.
|
77
|
+
gem 'sweet-moon', '~> 0.0.6'
|
73
78
|
```
|
74
79
|
|
75
80
|
```ruby
|
@@ -209,6 +214,7 @@ Compared to: [rufus-lua](https://github.com/jmettraux/rufus-lua), [YAML](https:/
|
|
209
214
|
- [Tables, Arrays, and Hashes](#tables-arrays-and-hashes)
|
210
215
|
- [Functions](#functions)
|
211
216
|
- [Other Types](#other-types)
|
217
|
+
- [Lua Global vs Local Variables](#lua-global-vs-local-variables)
|
212
218
|
- [_destroy_ and _clear_](#destroy-and-clear)
|
213
219
|
|
214
220
|
### Setup
|
@@ -389,6 +395,20 @@ state.eval('lua_value = {a = "text", b = 1.5, c = true}') # => nil
|
|
389
395
|
state.get(:lua_value, :b) # => 1.5
|
390
396
|
```
|
391
397
|
|
398
|
+
With `set`, you can use a second parameter to set a field:
|
399
|
+
|
400
|
+
```ruby
|
401
|
+
require 'sweet-moon'
|
402
|
+
|
403
|
+
state = SweetMoon::State.new
|
404
|
+
|
405
|
+
state.set(:myTable, {}) # => nil
|
406
|
+
|
407
|
+
state.set(:myTable, :a, 3) # => nil
|
408
|
+
|
409
|
+
state.eval('return myTable["a"]') # => 3
|
410
|
+
```
|
411
|
+
|
392
412
|
Caveats:
|
393
413
|
|
394
414
|
- Ruby `Symbol` (e.g. `:value`) is converted to Lua `string`.
|
@@ -512,6 +532,24 @@ fennel_eval = state.get(:fennel_eval)
|
|
512
532
|
fennel_eval.(['(+ 1 1)']) # => 2
|
513
533
|
```
|
514
534
|
|
535
|
+
#### Lua Global vs Local Variables
|
536
|
+
|
537
|
+
You can't exchange _local_ variables, only [_global_](https://www.lua.org/pil/1.2.html) ones:
|
538
|
+
|
539
|
+
```ruby
|
540
|
+
require 'sweet-moon'
|
541
|
+
|
542
|
+
state = SweetMoon::State.new
|
543
|
+
|
544
|
+
state.eval('lua_value = "Lua Text"') # => nil
|
545
|
+
|
546
|
+
state.get('lua_value') # => 'Lua Text'
|
547
|
+
|
548
|
+
state.eval('local lua_b = "b"') # => nil
|
549
|
+
|
550
|
+
state.get('lua_b') # => nil
|
551
|
+
```
|
552
|
+
|
515
553
|
## _destroy_ and _clear_
|
516
554
|
|
517
555
|
You can destroy a state:
|
@@ -577,21 +615,21 @@ state.add_package_path('/home/me/my-lua-modules/?/init.lua')
|
|
577
615
|
|
578
616
|
state.add_package_cpath('/home/me/my-lua-modules/?.so')
|
579
617
|
|
580
|
-
state.add_package_path('/home/me/fennel
|
618
|
+
state.add_package_path('/home/me/fennel/?.lua')
|
581
619
|
|
582
|
-
state.add_package_cpath('/home/me
|
620
|
+
state.add_package_cpath('/home/me/?.so')
|
583
621
|
|
584
622
|
state.package_path
|
585
623
|
# => ['./?.lua',
|
586
624
|
# './?/init.lua',
|
587
625
|
# '/home/me/my-lua-modules/?.lua',
|
588
626
|
# '/home/me/my-lua-modules/?/init.lua',
|
589
|
-
# '/home/me/fennel
|
627
|
+
# '/home/me/fennel/?.lua']
|
590
628
|
|
591
629
|
state.package_cpath
|
592
630
|
# => ['./?.so',
|
593
631
|
# '/home/me/my-lua-modules/?.so',
|
594
|
-
# '/home/me
|
632
|
+
# '/home/me/?.so']
|
595
633
|
```
|
596
634
|
|
597
635
|
Requiring a module:
|
@@ -611,8 +649,8 @@ You can set packages in State constructors:
|
|
611
649
|
require 'sweet-moon'
|
612
650
|
|
613
651
|
SweetMoon::State.new(
|
614
|
-
package_path: '/folder/lib
|
615
|
-
package_cpath: '/lib/lib
|
652
|
+
package_path: '/folder/lib/?.lua',
|
653
|
+
package_cpath: '/lib/lib/?.so',
|
616
654
|
)
|
617
655
|
```
|
618
656
|
|
@@ -622,8 +660,8 @@ Also, you can add packages through the global config:
|
|
622
660
|
require 'sweet-moon'
|
623
661
|
|
624
662
|
SweetMoon.global.config(
|
625
|
-
package_path: '/folder/lib
|
626
|
-
package_cpath: '/lib/lib
|
663
|
+
package_path: '/folder/lib/?.lua',
|
664
|
+
package_cpath: '/lib/lib/?.so',
|
627
665
|
)
|
628
666
|
```
|
629
667
|
|
@@ -714,8 +752,8 @@ state = SweetMoon::State.new
|
|
714
752
|
|
715
753
|
state.fennel.eval('(+ 1 2)') # => 3
|
716
754
|
|
717
|
-
state.fennel.eval('(
|
718
|
-
state.fennel.eval('(mySum 2 3)') # => 5
|
755
|
+
state.fennel.eval('(set _G.mySum (fn [a b] (+ a b)))')
|
756
|
+
state.fennel.eval('(_G.mySum 2 3)') # => 5
|
719
757
|
|
720
758
|
mySum = state.fennel.get(:mySum)
|
721
759
|
|
@@ -725,7 +763,7 @@ sum_list = -> (list) { list.sum }
|
|
725
763
|
|
726
764
|
state.set('sumList', sum_list) # => nil
|
727
765
|
|
728
|
-
state.fennel.eval('(sumList [2 3 5])') # => 10
|
766
|
+
state.fennel.eval('(_G.sumList [2 3 5])') # => 10
|
729
767
|
|
730
768
|
state.fennel.load('file.fnl')
|
731
769
|
```
|
@@ -740,6 +778,49 @@ state = SweetMoon::State.new.fennel
|
|
740
778
|
state.eval('(+ 1 2)') # => 3
|
741
779
|
```
|
742
780
|
|
781
|
+
### Fennel Global vs Local Variables
|
782
|
+
|
783
|
+
Fennel encourages you to explicitly use the [_`_G`_](https://www.lua.org/manual/5.4/manual.html#pdf-_G) table to access global variables:
|
784
|
+
|
785
|
+
```ruby
|
786
|
+
require 'sweet-moon'
|
787
|
+
|
788
|
+
fennel = SweetMoon::State.new.fennel
|
789
|
+
|
790
|
+
fennel.eval('(set _G.a? 2)')
|
791
|
+
|
792
|
+
fennel.get('a?') # => 2
|
793
|
+
fennel.get('_G', 'a?') # => 2
|
794
|
+
|
795
|
+
fennel.set('b', 3)
|
796
|
+
|
797
|
+
fennel.eval('(print _G.b)') # => 3
|
798
|
+
```
|
799
|
+
|
800
|
+
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.
|
801
|
+
|
802
|
+
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:
|
803
|
+
|
804
|
+
```ruby
|
805
|
+
require 'sweet-moon'
|
806
|
+
|
807
|
+
fennel = SweetMoon::State.new.fennel
|
808
|
+
|
809
|
+
fennel.eval('(local name "value")')
|
810
|
+
|
811
|
+
fennel.get('name') # => nil
|
812
|
+
|
813
|
+
fennel.eval('(set _G.name "value")')
|
814
|
+
|
815
|
+
fennel.get('name') # => "value"
|
816
|
+
|
817
|
+
fennel.set('var-b', 35) # => nil
|
818
|
+
|
819
|
+
fennel.eval('var-b') # => nil
|
820
|
+
|
821
|
+
fennel.eval('_G.var-b') # => 35
|
822
|
+
```
|
823
|
+
|
743
824
|
### Fennel Setup
|
744
825
|
|
745
826
|
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 +834,7 @@ require 'sweet-moon'
|
|
753
834
|
|
754
835
|
state = SweetMoon::State.new
|
755
836
|
|
756
|
-
state.add_package_path('/folder/fennel
|
837
|
+
state.add_package_path('/folder/fennel/?.lua')
|
757
838
|
|
758
839
|
state.fennel.eval('(+ 1 1)') # => 2
|
759
840
|
```
|
@@ -763,7 +844,7 @@ With the constructor:
|
|
763
844
|
```ruby
|
764
845
|
require 'sweet-moon'
|
765
846
|
|
766
|
-
fennel = SweetMoon::State.new(package_path: '/folder/fennel
|
847
|
+
fennel = SweetMoon::State.new(package_path: '/folder/fennel/?.lua').fennel
|
767
848
|
|
768
849
|
fennel.eval('(+ 1 1)') # => 2
|
769
850
|
```
|
@@ -773,7 +854,7 @@ With global:
|
|
773
854
|
```ruby
|
774
855
|
require 'sweet-moon'
|
775
856
|
|
776
|
-
SweetMoon.global.state.add_package_path('/folder/fennel
|
857
|
+
SweetMoon.global.state.add_package_path('/folder/fennel/?.lua')
|
777
858
|
|
778
859
|
SweetMoon.global.state.fennel.eval('(+ 1 1)') # => 2
|
779
860
|
```
|
@@ -783,7 +864,7 @@ Alternatively:
|
|
783
864
|
```ruby
|
784
865
|
require 'sweet-moon'
|
785
866
|
|
786
|
-
SweetMoon.global.config(package_path: '/folder/fennel
|
867
|
+
SweetMoon.global.config(package_path: '/folder/fennel/?.lua')
|
787
868
|
|
788
869
|
SweetMoon.global.state.fennel.eval('(+ 1 1)') # => 2
|
789
870
|
```
|
@@ -810,6 +891,44 @@ To enforce the path for the `.fnx.fnl` file:
|
|
810
891
|
fennel.eval('(let [fnx (require :fnx)] (fnx.bootstrap! "/project/.fnx.fnl"))')
|
811
892
|
```
|
812
893
|
|
894
|
+
### Fennel REPL
|
895
|
+
|
896
|
+
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):
|
897
|
+
|
898
|
+
```ruby
|
899
|
+
require 'pry'
|
900
|
+
|
901
|
+
binding.pry
|
902
|
+
```
|
903
|
+
|
904
|
+
The same is true for Fennel, you just need to:
|
905
|
+
```fnl
|
906
|
+
(let [fennel (require :fennel)]
|
907
|
+
(fennel.repl {}))
|
908
|
+
```
|
909
|
+
|
910
|
+
Fennel's REPL won't have your _local_ values. But, you can tweak it to receive values to be checked inside the REPL:
|
911
|
+
|
912
|
+
```fnl
|
913
|
+
(fn my-repl [to-expose]
|
914
|
+
(let [fennel (require :fennel) env _G]
|
915
|
+
(each [key value (pairs to-expose)] (tset env key value))
|
916
|
+
(fennel.repl {:env env})))
|
917
|
+
|
918
|
+
(local value "some value")
|
919
|
+
|
920
|
+
(my-repl {:value value})
|
921
|
+
|
922
|
+
; Inside the REPL:
|
923
|
+
|
924
|
+
; >> value
|
925
|
+
; "some value"
|
926
|
+
```
|
927
|
+
|
928
|
+
You can install [_readline_](https://luarocks.org/modules/peterbillam/readline) for a better experience, e.g., autocompleting.
|
929
|
+
|
930
|
+
> _Check [Fennel's documentation](https://fennel-lang.org/api#start-a-configurable-repl) to learn more about the REPL._
|
931
|
+
|
813
932
|
## Global vs Isolated
|
814
933
|
|
815
934
|
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):
|
@@ -856,6 +975,8 @@ api_5.luaL_newstate
|
|
856
975
|
api_3.luaH_new
|
857
976
|
```
|
858
977
|
|
978
|
+
> _Check the caveats related to [_Global FFI_](#global-ffi) when working with multiple versions._
|
979
|
+
|
859
980
|
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.
|
860
981
|
|
861
982
|
So, you can at any time create a new isolated _State_ and destroy it when you don't need it anymore:
|
@@ -885,6 +1006,48 @@ state_5.eval('return _VERSION') # => Lua 5.4
|
|
885
1006
|
state_3.eval('return _VERSION') # => Lua 3.2
|
886
1007
|
```
|
887
1008
|
|
1009
|
+
> _Check the caveats related to [_Global FFI_](#global-ffi) when working with multiple versions._
|
1010
|
+
|
1011
|
+
## Global FFI
|
1012
|
+
|
1013
|
+
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.
|
1014
|
+
|
1015
|
+
By default, _Sweet Moon_ enables [_Global FFI_](https://github.com/ffi/ffi/wiki/Loading-Libraries#function-visibility) to reduce friction when using popular libraries.
|
1016
|
+
|
1017
|
+
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.
|
1018
|
+
|
1019
|
+
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.
|
1020
|
+
|
1021
|
+
You can disable _Global FFI_ at any time with:
|
1022
|
+
|
1023
|
+
```ruby
|
1024
|
+
require 'sweet-moon'
|
1025
|
+
|
1026
|
+
SweetMoon.global.config(global_ffi: false)
|
1027
|
+
|
1028
|
+
SweetMoon::State.new(global_ffi: false)
|
1029
|
+
|
1030
|
+
SweetMoon::API.new(global_ffi: false)
|
1031
|
+
```
|
1032
|
+
|
1033
|
+
To check if it's enabled or not:
|
1034
|
+
|
1035
|
+
```ruby
|
1036
|
+
require 'sweet-moon'
|
1037
|
+
|
1038
|
+
SweetMoon.global.api.meta.global_ffi # => true
|
1039
|
+
SweetMoon.global.state.meta.global_ffi # => true
|
1040
|
+
|
1041
|
+
SweetMoon::API.new.meta.global_ffi # => true
|
1042
|
+
|
1043
|
+
SweetMoon::State.new.meta.global_ffi # => true
|
1044
|
+
```
|
1045
|
+
|
1046
|
+
**Caveats:**
|
1047
|
+
|
1048
|
+
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.
|
1049
|
+
|
1050
|
+
Also, the simple action of accessing `meta.global_ff` will bind the API, so you need to set your desired configuration before checking.
|
888
1051
|
|
889
1052
|
## Error Handling
|
890
1053
|
|
@@ -929,6 +1092,108 @@ rescue LuaRuntimeError => error
|
|
929
1092
|
end
|
930
1093
|
```
|
931
1094
|
|
1095
|
+
### Ruby feat. Lua Errors
|
1096
|
+
|
1097
|
+
Lua errors can be rescued inside Ruby:
|
1098
|
+
|
1099
|
+
```lua
|
1100
|
+
-- source.lua
|
1101
|
+
error('error from lua')
|
1102
|
+
```
|
1103
|
+
|
1104
|
+
```ruby
|
1105
|
+
require 'sweet-moon'
|
1106
|
+
require 'sweet-moon/errors'
|
1107
|
+
|
1108
|
+
state = SweetMoon::State.new
|
1109
|
+
|
1110
|
+
begin
|
1111
|
+
state.load('source.lua')
|
1112
|
+
rescue LuaRuntimeError => e
|
1113
|
+
puts e.message
|
1114
|
+
# => source.lua:2: error from lua
|
1115
|
+
end
|
1116
|
+
```
|
1117
|
+
|
1118
|
+
Ruby errors can be handled inside Lua:
|
1119
|
+
|
1120
|
+
```ruby
|
1121
|
+
require 'sweet-moon'
|
1122
|
+
|
1123
|
+
state = SweetMoon::State.new
|
1124
|
+
|
1125
|
+
state.set(:rubyFn, -> { raise 'error from ruby' })
|
1126
|
+
|
1127
|
+
state.load('source.lua')
|
1128
|
+
```
|
1129
|
+
|
1130
|
+
```lua
|
1131
|
+
-- source.lua
|
1132
|
+
local status, err = pcall(rubyFn)
|
1133
|
+
|
1134
|
+
print(status) -- => false
|
1135
|
+
|
1136
|
+
print(err)
|
1137
|
+
-- [string " return function (...)..."]:5: RuntimeError: error from ruby stack traceback:
|
1138
|
+
-- [string " return function (...)..."]:5: in function 'rubyFn'
|
1139
|
+
-- [C]: in function 'pcall'
|
1140
|
+
-- source.lua:2: in main chunk
|
1141
|
+
```
|
1142
|
+
|
1143
|
+
Ruby errors not handled inside Lua can be rescued inside Ruby again, with an additional Lua backtrace:
|
1144
|
+
|
1145
|
+
```lua
|
1146
|
+
-- source.lua
|
1147
|
+
a = 1
|
1148
|
+
|
1149
|
+
rubyFn()
|
1150
|
+
```
|
1151
|
+
|
1152
|
+
```ruby
|
1153
|
+
require 'sweet-moon'
|
1154
|
+
|
1155
|
+
state = SweetMoon::State.new
|
1156
|
+
|
1157
|
+
state.set(:rubyFn, -> { raise 'error from ruby' })
|
1158
|
+
|
1159
|
+
begin
|
1160
|
+
state.load('source.lua')
|
1161
|
+
rescue RuntimeError => e
|
1162
|
+
puts e.message # => error from ruby
|
1163
|
+
|
1164
|
+
puts e.backtrace.last
|
1165
|
+
# => source.lua:4: in main chunk
|
1166
|
+
end
|
1167
|
+
```
|
1168
|
+
|
1169
|
+
Lua errors inside Lua functions can be rescued inside Ruby:
|
1170
|
+
|
1171
|
+
```lua
|
1172
|
+
-- source.lua
|
1173
|
+
function luaFn()
|
1174
|
+
error('lua function error')
|
1175
|
+
end
|
1176
|
+
```
|
1177
|
+
|
1178
|
+
```ruby
|
1179
|
+
require 'sweet-moon'
|
1180
|
+
require 'sweet-moon/errors'
|
1181
|
+
|
1182
|
+
state = SweetMoon::State.new
|
1183
|
+
|
1184
|
+
state.load('source.lua')
|
1185
|
+
|
1186
|
+
lua_fn = state.get(:luaFn)
|
1187
|
+
|
1188
|
+
begin
|
1189
|
+
lua_fn.()
|
1190
|
+
rescue LuaRuntimeError => e
|
1191
|
+
puts e.message # => "source.lua:3: lua function error"
|
1192
|
+
end
|
1193
|
+
```
|
1194
|
+
|
1195
|
+
For Fennel, all the examples above are equally true, with additional stack traceback as well.
|
1196
|
+
|
932
1197
|
## Where can I find .so files?
|
933
1198
|
|
934
1199
|
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.
|
@@ -1183,6 +1448,8 @@ Update the [`config/tests.yml`](https://github.com/gbaptista/sweet-moon/blob/mai
|
|
1183
1448
|
|
1184
1449
|
Alternatively: Find or build the _Shared Objects_ for your Operating System on your own.
|
1185
1450
|
|
1451
|
+
Install the expected Lua _rocks_ described in `config/tests.yml`.
|
1452
|
+
|
1186
1453
|
### Running
|
1187
1454
|
|
1188
1455
|
```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
|