sweet-moon 0.0.1
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 +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/.rubocop.yml +40 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +61 -0
- data/README.md +1149 -0
- data/components/api.rb +83 -0
- data/components/injections/injections_503.rb +21 -0
- data/components/injections/injections_514.rb +29 -0
- data/components/injections/injections_542.rb +49 -0
- data/components/injections.rb +11 -0
- data/components/interpreters/50/function.rb +52 -0
- data/components/interpreters/50/interpreter.rb +105 -0
- data/components/interpreters/50/reader.rb +65 -0
- data/components/interpreters/50/table.rb +99 -0
- data/components/interpreters/50/writer.rb +45 -0
- data/components/interpreters/51/function.rb +52 -0
- data/components/interpreters/51/interpreter.rb +104 -0
- data/components/interpreters/51/reader.rb +65 -0
- data/components/interpreters/51/table.rb +60 -0
- data/components/interpreters/51/writer.rb +45 -0
- data/components/interpreters/54/function.rb +52 -0
- data/components/interpreters/54/interpreter.rb +100 -0
- data/components/interpreters/54/reader.rb +65 -0
- data/components/interpreters/54/table.rb +60 -0
- data/components/interpreters/54/writer.rb +45 -0
- data/components/interpreters.rb +11 -0
- data/components/io.rb +11 -0
- data/config/tests.sample.yml +15 -0
- data/controllers/api.rb +143 -0
- data/controllers/cli/cli.rb +32 -0
- data/controllers/cli/help.rb +24 -0
- data/controllers/cli/signatures.rb +179 -0
- data/controllers/cli/version.rb +14 -0
- data/controllers/interpreter.rb +68 -0
- data/controllers/state.rb +74 -0
- data/dsl/api.rb +31 -0
- data/dsl/cache.rb +118 -0
- data/dsl/concerns/fennel.rb +13 -0
- data/dsl/concerns/packages.rb +37 -0
- data/dsl/errors.rb +28 -0
- data/dsl/fennel.rb +47 -0
- data/dsl/global.rb +42 -0
- data/dsl/state.rb +104 -0
- data/dsl/sweet_moon.rb +53 -0
- data/logic/api.rb +17 -0
- data/logic/interpreter.rb +84 -0
- data/logic/interpreters/interpreter_50.rb +34 -0
- data/logic/interpreters/interpreter_51.rb +37 -0
- data/logic/interpreters/interpreter_54.rb +41 -0
- data/logic/io.rb +6 -0
- data/logic/options.rb +14 -0
- data/logic/shared_object.rb +52 -0
- data/logic/signature.rb +258 -0
- data/logic/signatures/ffi_types.rb +27 -0
- data/logic/signatures/signatures_322.rb +418 -0
- data/logic/signatures/signatures_401.rb +243 -0
- data/logic/signatures/signatures_503.rb +575 -0
- data/logic/signatures/signatures_514.rb +460 -0
- data/logic/signatures/signatures_542.rb +591 -0
- data/logic/spec.rb +13 -0
- data/logic/tables.rb +32 -0
- data/ports/in/dsl/sweet-moon/errors.rb +3 -0
- data/ports/in/dsl/sweet-moon.rb +1 -0
- data/ports/in/shell/sweet-moon +5 -0
- data/ports/in/shell.rb +21 -0
- data/ports/out/shell.rb +9 -0
- data/sweet-moon.gemspec +35 -0
- metadata +137 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative '../errors'
|
2
|
+
|
3
|
+
module DSL
|
4
|
+
module Concerns
|
5
|
+
module Packages
|
6
|
+
def add_package_path(path, target = 'package.path')
|
7
|
+
_ensure_min_version!(target, '5.1', '2')
|
8
|
+
|
9
|
+
paths = path
|
10
|
+
paths = [path] unless paths.is_a? Array
|
11
|
+
|
12
|
+
self.eval("#{target} = #{target} .. \";#{paths.join(';')}\"")
|
13
|
+
end
|
14
|
+
|
15
|
+
def package_path(target = 'package.path')
|
16
|
+
_ensure_min_version!(target, '5.1', '2')
|
17
|
+
self.eval("return #{target}").split(';')
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_package_cpath(path)
|
21
|
+
add_package_path(path, 'package.cpath')
|
22
|
+
end
|
23
|
+
|
24
|
+
def package_cpath
|
25
|
+
package_path('package.cpath')
|
26
|
+
end
|
27
|
+
|
28
|
+
def require_module(module_name)
|
29
|
+
require_module_as(module_name, module_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def require_module_as(module_name, variable)
|
33
|
+
self.eval("#{variable} = require \"#{module_name}\"")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/dsl/errors.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module SweetMoon
|
2
|
+
module Errors
|
3
|
+
class SweetMoonError < StandardError; end
|
4
|
+
class LuaError < SweetMoonError; end
|
5
|
+
|
6
|
+
class LuaRuntimeError < LuaError; end
|
7
|
+
class LuaMemoryAllocationError < LuaError; end
|
8
|
+
class LuaMessageHandlerError < LuaError; end
|
9
|
+
class LuaSyntaxError < LuaError; end
|
10
|
+
class LuaFileError < LuaError; end
|
11
|
+
|
12
|
+
module SweetMoonErrorHelper
|
13
|
+
def for(status)
|
14
|
+
case status
|
15
|
+
when :runtime then LuaRuntimeError
|
16
|
+
when :memory_allocation then LuaMemoryAllocationError
|
17
|
+
when :message_handler then LuaMessageHandlerError
|
18
|
+
when :syntax then LuaSyntaxError
|
19
|
+
when :file then LuaFileError
|
20
|
+
else
|
21
|
+
LuaError
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module_function :for
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/dsl/fennel.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module DSL
|
2
|
+
class Fennel
|
3
|
+
attr_reader :meta
|
4
|
+
|
5
|
+
def initialize(state)
|
6
|
+
@state = state
|
7
|
+
|
8
|
+
@state.require_module(:fennel)
|
9
|
+
|
10
|
+
@state.eval(
|
11
|
+
'table.insert(package.loaders or package.searchers, fennel.searcher)'
|
12
|
+
)
|
13
|
+
|
14
|
+
@eval = @state.get(:fennel, :eval)
|
15
|
+
@dofile = @state.get(:fennel, :dofile)
|
16
|
+
@version = @state.get(:fennel, :version)
|
17
|
+
|
18
|
+
build_meta
|
19
|
+
end
|
20
|
+
|
21
|
+
def eval(input, outputs = 1)
|
22
|
+
@eval.([input], outputs)
|
23
|
+
end
|
24
|
+
|
25
|
+
def load(path, outputs = 1)
|
26
|
+
@dofile.([path], outputs)
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_meta
|
30
|
+
meta_data = @state.meta.to_h
|
31
|
+
|
32
|
+
meta_data = meta_data.merge(
|
33
|
+
runtime: "Fennel #{@version} on #{meta_data[:runtime]}"
|
34
|
+
)
|
35
|
+
|
36
|
+
@meta = Struct.new(*meta_data.keys).new(*meta_data.values)
|
37
|
+
end
|
38
|
+
|
39
|
+
def respond_to_missing?(method_name)
|
40
|
+
@state.respond_to? method_name
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_missing(method_name, *arguments, &block)
|
44
|
+
@state.public_send(method_name, *arguments, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/dsl/global.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative '../logic/options'
|
2
|
+
|
3
|
+
require_relative 'cache'
|
4
|
+
|
5
|
+
module Global
|
6
|
+
def api
|
7
|
+
Cache.instance.global_api
|
8
|
+
end
|
9
|
+
|
10
|
+
def state
|
11
|
+
Cache.instance.global_state
|
12
|
+
end
|
13
|
+
|
14
|
+
def config(options = {})
|
15
|
+
options = Logic::Options[:normalize].(options)
|
16
|
+
|
17
|
+
if options.key?(:shared_objects) || options.key?(:api_reference)
|
18
|
+
Cache.instance.global_api(options, recreate: true)
|
19
|
+
end
|
20
|
+
|
21
|
+
return unless
|
22
|
+
options.key?(:interpreter) ||
|
23
|
+
options.key?(:package_path) ||
|
24
|
+
options.key?(:package_cpath)
|
25
|
+
|
26
|
+
Cache.instance.global_state(options, recreate: true)
|
27
|
+
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def cached(all: false)
|
32
|
+
return Cache.instance.keys if all
|
33
|
+
|
34
|
+
Cache.instance.keys.select { |key| key[/^global/] }
|
35
|
+
end
|
36
|
+
|
37
|
+
def clear
|
38
|
+
Cache.instance.clear_global!
|
39
|
+
end
|
40
|
+
|
41
|
+
module_function :api, :state, :config, :cached, :clear
|
42
|
+
end
|
data/dsl/state.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require_relative 'errors'
|
2
|
+
require_relative 'concerns/packages'
|
3
|
+
require_relative 'concerns/fennel'
|
4
|
+
|
5
|
+
module DSL
|
6
|
+
class State
|
7
|
+
include DSL::Concerns::Packages
|
8
|
+
include DSL::Concerns::Fennel
|
9
|
+
|
10
|
+
attr_reader :meta
|
11
|
+
|
12
|
+
def initialize(api_component, interpreter_component, controller, options = {})
|
13
|
+
@api = api_component[:api]
|
14
|
+
@interpreter = interpreter_component[:interpreter]
|
15
|
+
@controller = controller
|
16
|
+
|
17
|
+
@state = @controller[:create!].(@api, @interpreter)[:state]
|
18
|
+
|
19
|
+
build_meta(api_component, interpreter_component)
|
20
|
+
|
21
|
+
add_package_path(options[:package_path]) if options[:package_path]
|
22
|
+
add_package_cpath(options[:package_cpath]) if options[:package_cpath]
|
23
|
+
end
|
24
|
+
|
25
|
+
def eval(input, outputs = 1)
|
26
|
+
@controller[:eval!].(@api, @interpreter, state, input, outputs)[:output]
|
27
|
+
end
|
28
|
+
|
29
|
+
def load(path, outputs = 1)
|
30
|
+
@controller[:load!].(@api, @interpreter, state, path, outputs)[:output]
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(variable, key = nil)
|
34
|
+
@controller[:get!].(@api, @interpreter, state, variable, key)[:output]
|
35
|
+
end
|
36
|
+
|
37
|
+
def set(variable, value)
|
38
|
+
@controller[:set!].(@api, @interpreter, state, variable, value)[:output]
|
39
|
+
end
|
40
|
+
|
41
|
+
def destroy
|
42
|
+
@controller[:destroy!].(@api, @interpreter, state) if @state
|
43
|
+
@state = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def clear
|
47
|
+
@controller[:destroy!].(@api, @interpreter, state) if @state
|
48
|
+
@state = @controller[:create!].(@api, @interpreter)[:state]
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def _ensure_min_version!(purpose, lua, jit = nil)
|
53
|
+
version = lua
|
54
|
+
version = jit if meta.interpreter[/jit/] && jit
|
55
|
+
|
56
|
+
return unless Gem::Version.new(
|
57
|
+
meta.interpreter.gsub(/.+:/, '')
|
58
|
+
) < Gem::Version.new(version)
|
59
|
+
|
60
|
+
message = "#{purpose} requires Lua >= #{lua}"
|
61
|
+
message = "#{message} or LuaJIT >= #{jit}" if jit
|
62
|
+
|
63
|
+
raise SweetMoon::Errors::SweetMoonError,
|
64
|
+
"#{message}; Current: #{meta.runtime} (#{meta.interpreter})"
|
65
|
+
end
|
66
|
+
|
67
|
+
def _unsafely_destroy
|
68
|
+
@controller[:destroy!].(@api, @interpreter, state)
|
69
|
+
@state = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def inspect
|
73
|
+
output = "#<#{self.class}:0x#{format('%016x', object_id)}"
|
74
|
+
|
75
|
+
variables = ['@meta'].map do |struct_name|
|
76
|
+
"#{struct_name}=#{instance_variable_get(struct_name).inspect}"
|
77
|
+
end
|
78
|
+
|
79
|
+
"#{output} #{variables.join(' ')}>"
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def build_meta(api_component, interpreter_component)
|
85
|
+
meta_data = {
|
86
|
+
api_reference: api_component[:meta][:elected][:api_reference],
|
87
|
+
shared_objects: api_component[:meta][:elected][:shared_objects],
|
88
|
+
interpreter: interpreter_component[:meta][:elected][:interpreter],
|
89
|
+
runtime: interpreter_component[:meta][:runtime][:lua]
|
90
|
+
}
|
91
|
+
|
92
|
+
@meta = Struct.new(*meta_data.keys).new(*meta_data.values)
|
93
|
+
end
|
94
|
+
|
95
|
+
def state
|
96
|
+
unless @state
|
97
|
+
raise SweetMoon::Errors::SweetMoonError,
|
98
|
+
'The state no longer exists.'
|
99
|
+
end
|
100
|
+
|
101
|
+
@state
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/dsl/sweet_moon.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require_relative '../logic/options'
|
2
|
+
require_relative '../logic/spec'
|
3
|
+
|
4
|
+
require_relative 'cache'
|
5
|
+
require_relative 'state'
|
6
|
+
require_relative 'global'
|
7
|
+
|
8
|
+
require_relative '../logic/api'
|
9
|
+
require_relative '../logic/interpreter'
|
10
|
+
|
11
|
+
module SweetMoon
|
12
|
+
module API
|
13
|
+
def new(options = {})
|
14
|
+
Cache.instance.api(Logic::Options[:normalize].(options))
|
15
|
+
end
|
16
|
+
|
17
|
+
module_function :new
|
18
|
+
end
|
19
|
+
|
20
|
+
module State
|
21
|
+
def new(options = {})
|
22
|
+
options = Logic::Options[:normalize].(options)
|
23
|
+
|
24
|
+
api = Cache.instance.api_module(options)
|
25
|
+
|
26
|
+
interpreter = Cache.instance.interpreter_module(api, options)
|
27
|
+
|
28
|
+
DSL::State.new(api, interpreter, Controller::State, options)
|
29
|
+
end
|
30
|
+
|
31
|
+
module_function :new
|
32
|
+
end
|
33
|
+
|
34
|
+
def meta
|
35
|
+
meta_data = {
|
36
|
+
version: Logic::Spec[:version],
|
37
|
+
api_references: Logic::API[:candidates].values.map do |candidate|
|
38
|
+
candidate[:version]
|
39
|
+
end,
|
40
|
+
interpreters: Logic::Interpreter[:candidates].values.map do |candidate|
|
41
|
+
candidate[:version]
|
42
|
+
end
|
43
|
+
}
|
44
|
+
|
45
|
+
Struct.new(*meta_data.keys).new(*meta_data.values)
|
46
|
+
end
|
47
|
+
|
48
|
+
def global
|
49
|
+
Global
|
50
|
+
end
|
51
|
+
|
52
|
+
module_function :meta, :global
|
53
|
+
end
|
data/logic/api.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'signatures/signatures_322'
|
2
|
+
require_relative 'signatures/signatures_401'
|
3
|
+
require_relative 'signatures/signatures_503'
|
4
|
+
require_relative 'signatures/signatures_514'
|
5
|
+
require_relative 'signatures/signatures_542'
|
6
|
+
|
7
|
+
module Logic
|
8
|
+
API = {
|
9
|
+
candidates: {
|
10
|
+
'3.2.2' => { version: '3.2.2', signatures: V322::Signatures },
|
11
|
+
'4.0.1' => { version: '4.0.1', signatures: V401::Signatures },
|
12
|
+
'5.0.3' => { version: '5.0.3', signatures: V503::Signatures },
|
13
|
+
'5.1.4' => { version: '5.1.4', signatures: V514::Signatures },
|
14
|
+
'5.4.2' => { version: '5.4.2', signatures: V542::Signatures }
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative 'interpreters/interpreter_50'
|
2
|
+
require_relative 'interpreters/interpreter_51'
|
3
|
+
require_relative 'interpreters/interpreter_54'
|
4
|
+
|
5
|
+
module Logic
|
6
|
+
Interpreter = {
|
7
|
+
candidates: {
|
8
|
+
'5.0' => { version: '5.0', requires: V50::Interpreter[:requires] },
|
9
|
+
'5.1' => { version: '5.1', requires: V51::Interpreter[:requires] },
|
10
|
+
'5.4' => { version: '5.4', requires: V54::Interpreter[:requires] }
|
11
|
+
},
|
12
|
+
|
13
|
+
elect: ->(signatures, api_version, options = {}) {
|
14
|
+
interpreters = Interpreter[:candidates].values
|
15
|
+
|
16
|
+
if options[:interpreter]
|
17
|
+
interpreters = interpreters.select do |interpreter|
|
18
|
+
interpreter[:version].to_s == options[:interpreter]
|
19
|
+
end
|
20
|
+
|
21
|
+
if interpreters.size.zero?
|
22
|
+
return {
|
23
|
+
compatible: false,
|
24
|
+
error: "Interpreter #{options[:interpreter]} not available."
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
results = {}
|
30
|
+
|
31
|
+
interpreters.each do |interpreter|
|
32
|
+
results[interpreter[:version]] = Interpreter[:check_compatibility].(
|
33
|
+
interpreter, signatures
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
result = Interpreter[:choose_compatible].(results)
|
38
|
+
|
39
|
+
return result if result
|
40
|
+
|
41
|
+
{ compatible: false,
|
42
|
+
error: Interpreter[:closest_error_message].(api_version, results) }
|
43
|
+
},
|
44
|
+
|
45
|
+
closest_error_message: ->(api_version, candidates) {
|
46
|
+
closest = candidates.values.sort_by do |candidate|
|
47
|
+
Gem::Version.new(candidate[:version].gsub(/.+:/, '') || '0')
|
48
|
+
end.reverse
|
49
|
+
|
50
|
+
closest = closest.min_by { |candidate| candidate[:missing].size }
|
51
|
+
|
52
|
+
message = "Missing in the closest version (#{closest[:version]}):"
|
53
|
+
|
54
|
+
closest[:missing].sort.each_slice(4).each do |functions|
|
55
|
+
message += "\n #{functions.join(' ')}"
|
56
|
+
end
|
57
|
+
|
58
|
+
"No compatible interpreter found for Lua C API #{api_version}.\n#{message}"
|
59
|
+
},
|
60
|
+
|
61
|
+
choose_compatible: ->(candidates) {
|
62
|
+
candidates = candidates.values.select do |candidate|
|
63
|
+
candidate[:compatible]
|
64
|
+
end
|
65
|
+
|
66
|
+
candidates.max_by do |candidate|
|
67
|
+
Gem::Version.new(candidate[:version].gsub(/.+:/, '') || '0')
|
68
|
+
end
|
69
|
+
},
|
70
|
+
|
71
|
+
check_compatibility: ->(interpreter, signatures) {
|
72
|
+
result = { version: interpreter[:version], compatible: true, missing: [] }
|
73
|
+
|
74
|
+
interpreter[:requires].each do |required|
|
75
|
+
unless signatures[required]
|
76
|
+
result[:compatible] = false
|
77
|
+
result[:missing] << required
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
result
|
82
|
+
}
|
83
|
+
}
|
84
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Logic
|
2
|
+
module V50
|
3
|
+
Interpreter = {
|
4
|
+
version: '5.0',
|
5
|
+
|
6
|
+
LUA_REGISTRYINDEX: -10_000,
|
7
|
+
LUA_GLOBALSINDEX: -10_001,
|
8
|
+
|
9
|
+
requires: %i[
|
10
|
+
lua_close lua_gettable lua_gettop lua_insert lua_newtable lua_next lua_open
|
11
|
+
lua_pcall lua_pushboolean lua_pushcclosure lua_pushnil lua_pushnumber
|
12
|
+
lua_pushstring lua_rawgeti lua_settable lua_settop lua_toboolean lua_tonumber
|
13
|
+
lua_topointer lua_tostring lua_type lua_typename luaL_loadbuffer luaL_loadfile
|
14
|
+
luaL_ref luaopen_base luaopen_io luaopen_math luaopen_string luaopen_table
|
15
|
+
],
|
16
|
+
|
17
|
+
status: {
|
18
|
+
1 => :LUA_ERRRUN,
|
19
|
+
2 => :LUA_ERRFILE,
|
20
|
+
3 => :LUA_ERRSYNTAX,
|
21
|
+
4 => :LUA_ERRMEM,
|
22
|
+
5 => :LUA_ERRERR
|
23
|
+
},
|
24
|
+
|
25
|
+
error: {
|
26
|
+
LUA_ERRRUN: :runtime,
|
27
|
+
LUA_ERRFILE: :file,
|
28
|
+
LUA_ERRSYNTAX: :syntax,
|
29
|
+
LUA_ERRMEM: :memory_allocation,
|
30
|
+
LUA_ERRERR: :message_handler
|
31
|
+
}
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Logic
|
2
|
+
module V51
|
3
|
+
Interpreter = {
|
4
|
+
version: '5.1',
|
5
|
+
|
6
|
+
LUA_REGISTRYINDEX: -10_000,
|
7
|
+
LUA_GLOBALSINDEX: -10_002,
|
8
|
+
|
9
|
+
# lua_isinteger lua_pushinteger lua_tointeger
|
10
|
+
requires: %i[
|
11
|
+
lua_close lua_createtable lua_getfield lua_gettable lua_gettop lua_insert
|
12
|
+
lua_next lua_pcall lua_pushboolean lua_pushcclosure lua_pushnil lua_pushnumber
|
13
|
+
lua_pushstring lua_rawgeti lua_settable lua_settop lua_toboolean lua_tonumber
|
14
|
+
lua_topointer lua_tostring lua_type lua_typename luaL_loadfile luaL_loadstring
|
15
|
+
luaL_newstate luaL_openlibs luaL_ref
|
16
|
+
],
|
17
|
+
|
18
|
+
status: {
|
19
|
+
0 => :LUA_OK,
|
20
|
+
1 => :LUA_YIELD,
|
21
|
+
2 => :LUA_ERRRUN,
|
22
|
+
3 => :LUA_ERRSYNTAX,
|
23
|
+
4 => :LUA_ERRMEM,
|
24
|
+
5 => :LUA_ERRERR,
|
25
|
+
6 => :LUA_ERRFILE
|
26
|
+
},
|
27
|
+
|
28
|
+
error: {
|
29
|
+
LUA_ERRRUN: :runtime,
|
30
|
+
LUA_ERRSYNTAX: :syntax,
|
31
|
+
LUA_ERRMEM: :memory_allocation,
|
32
|
+
LUA_ERRERR: :message_handler,
|
33
|
+
LUA_ERRFILE: :file
|
34
|
+
}
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Logic
|
2
|
+
module V54
|
3
|
+
Interpreter = {
|
4
|
+
version: '5.4',
|
5
|
+
|
6
|
+
LUA_RIDX_GLOBALS: 2,
|
7
|
+
|
8
|
+
# TODO: It's possible to read C constants?
|
9
|
+
# LUAI_MAXSTACK = 1_000_000
|
10
|
+
# -LUAI_MAXSTACK - 1000
|
11
|
+
LUA_REGISTRYINDEX: -1_000_000 - 1000,
|
12
|
+
|
13
|
+
# lua_isinteger lua_pushinteger lua_tointeger
|
14
|
+
requires: %i[
|
15
|
+
lua_close lua_createtable lua_getfield lua_getglobal lua_gettop lua_next
|
16
|
+
lua_pcall lua_pushboolean lua_pushcclosure lua_pushnil lua_pushnumber
|
17
|
+
lua_pushstring lua_rawgeti lua_setglobal lua_settable lua_settop lua_toboolean
|
18
|
+
lua_tonumber lua_topointer lua_tostring lua_type lua_typename luaL_loadfile
|
19
|
+
luaL_loadstring luaL_newstate luaL_openlibs luaL_ref
|
20
|
+
],
|
21
|
+
|
22
|
+
status: {
|
23
|
+
0 => :LUA_OK,
|
24
|
+
1 => :LUA_YIELD,
|
25
|
+
2 => :LUA_ERRRUN,
|
26
|
+
3 => :LUA_ERRSYNTAX,
|
27
|
+
4 => :LUA_ERRMEM,
|
28
|
+
5 => :LUA_ERRERR,
|
29
|
+
6 => :LUA_ERRFILE
|
30
|
+
},
|
31
|
+
|
32
|
+
error: {
|
33
|
+
LUA_ERRRUN: :runtime,
|
34
|
+
LUA_ERRSYNTAX: :syntax,
|
35
|
+
LUA_ERRMEM: :memory_allocation,
|
36
|
+
LUA_ERRERR: :message_handler,
|
37
|
+
LUA_ERRFILE: :file
|
38
|
+
}
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
data/logic/io.rb
ADDED
data/logic/options.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Logic
|
2
|
+
Options = {
|
3
|
+
normalize: ->(original_options) {
|
4
|
+
options = original_options.clone
|
5
|
+
|
6
|
+
if options[:shared_object]
|
7
|
+
options[:shared_objects] = [options[:shared_object]]
|
8
|
+
options.delete(:shared_object)
|
9
|
+
end
|
10
|
+
|
11
|
+
options
|
12
|
+
}
|
13
|
+
}
|
14
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative './io'
|
2
|
+
|
3
|
+
module Logic
|
4
|
+
SharedObject = {
|
5
|
+
choose: ->(candidate_paths, options = {}) {
|
6
|
+
candidates = candidate_paths.map do |path|
|
7
|
+
SharedObject[:normalize].(path)
|
8
|
+
end
|
9
|
+
|
10
|
+
unless options[:jit].nil?
|
11
|
+
candidates = candidates.select do |candidate|
|
12
|
+
options[:jit] ? candidate[:inferences][:jit] : !candidate[:inferences][:jit]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
if options[:version]
|
17
|
+
candidates = candidates.select do |candidate|
|
18
|
+
if candidate[:inferences][:version]
|
19
|
+
!candidate[:inferences][:version][/#{options[:version]}/].nil?
|
20
|
+
else
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
elected = candidates.max_by do |candidate|
|
27
|
+
Gem::Version.new(candidate[:inferences][:version] || '0')
|
28
|
+
end
|
29
|
+
|
30
|
+
return [] if elected.nil?
|
31
|
+
|
32
|
+
[elected]
|
33
|
+
},
|
34
|
+
|
35
|
+
normalize: ->(path) {
|
36
|
+
inferred_versions = IO[:file_name].(
|
37
|
+
path
|
38
|
+
).scan(/(\d+(\.\d+)*)/).map(&:first)
|
39
|
+
|
40
|
+
inferred_versions = inferred_versions.map do |inferred_version|
|
41
|
+
inferred_version.split('.').map { |part| part.chars.join('.') }.join('.')
|
42
|
+
end
|
43
|
+
|
44
|
+
inferred_version = inferred_versions.max_by do |raw_inferred_version|
|
45
|
+
Gem::Version.new(raw_inferred_version || '0')
|
46
|
+
end
|
47
|
+
|
48
|
+
{ path: path,
|
49
|
+
inferences: { jit: !path[/jit/].nil?, version: inferred_version } }
|
50
|
+
}
|
51
|
+
}
|
52
|
+
end
|