sweet-moon 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +40 -0
  5. data/Gemfile +12 -0
  6. data/Gemfile.lock +61 -0
  7. data/README.md +1149 -0
  8. data/components/api.rb +83 -0
  9. data/components/injections/injections_503.rb +21 -0
  10. data/components/injections/injections_514.rb +29 -0
  11. data/components/injections/injections_542.rb +49 -0
  12. data/components/injections.rb +11 -0
  13. data/components/interpreters/50/function.rb +52 -0
  14. data/components/interpreters/50/interpreter.rb +105 -0
  15. data/components/interpreters/50/reader.rb +65 -0
  16. data/components/interpreters/50/table.rb +99 -0
  17. data/components/interpreters/50/writer.rb +45 -0
  18. data/components/interpreters/51/function.rb +52 -0
  19. data/components/interpreters/51/interpreter.rb +104 -0
  20. data/components/interpreters/51/reader.rb +65 -0
  21. data/components/interpreters/51/table.rb +60 -0
  22. data/components/interpreters/51/writer.rb +45 -0
  23. data/components/interpreters/54/function.rb +52 -0
  24. data/components/interpreters/54/interpreter.rb +100 -0
  25. data/components/interpreters/54/reader.rb +65 -0
  26. data/components/interpreters/54/table.rb +60 -0
  27. data/components/interpreters/54/writer.rb +45 -0
  28. data/components/interpreters.rb +11 -0
  29. data/components/io.rb +11 -0
  30. data/config/tests.sample.yml +15 -0
  31. data/controllers/api.rb +143 -0
  32. data/controllers/cli/cli.rb +32 -0
  33. data/controllers/cli/help.rb +24 -0
  34. data/controllers/cli/signatures.rb +179 -0
  35. data/controllers/cli/version.rb +14 -0
  36. data/controllers/interpreter.rb +68 -0
  37. data/controllers/state.rb +74 -0
  38. data/dsl/api.rb +31 -0
  39. data/dsl/cache.rb +118 -0
  40. data/dsl/concerns/fennel.rb +13 -0
  41. data/dsl/concerns/packages.rb +37 -0
  42. data/dsl/errors.rb +28 -0
  43. data/dsl/fennel.rb +47 -0
  44. data/dsl/global.rb +42 -0
  45. data/dsl/state.rb +104 -0
  46. data/dsl/sweet_moon.rb +53 -0
  47. data/logic/api.rb +17 -0
  48. data/logic/interpreter.rb +84 -0
  49. data/logic/interpreters/interpreter_50.rb +34 -0
  50. data/logic/interpreters/interpreter_51.rb +37 -0
  51. data/logic/interpreters/interpreter_54.rb +41 -0
  52. data/logic/io.rb +6 -0
  53. data/logic/options.rb +14 -0
  54. data/logic/shared_object.rb +52 -0
  55. data/logic/signature.rb +258 -0
  56. data/logic/signatures/ffi_types.rb +27 -0
  57. data/logic/signatures/signatures_322.rb +418 -0
  58. data/logic/signatures/signatures_401.rb +243 -0
  59. data/logic/signatures/signatures_503.rb +575 -0
  60. data/logic/signatures/signatures_514.rb +460 -0
  61. data/logic/signatures/signatures_542.rb +591 -0
  62. data/logic/spec.rb +13 -0
  63. data/logic/tables.rb +32 -0
  64. data/ports/in/dsl/sweet-moon/errors.rb +3 -0
  65. data/ports/in/dsl/sweet-moon.rb +1 -0
  66. data/ports/in/shell/sweet-moon +5 -0
  67. data/ports/in/shell.rb +21 -0
  68. data/ports/out/shell.rb +9 -0
  69. data/sweet-moon.gemspec +35 -0
  70. metadata +137 -0
@@ -0,0 +1,258 @@
1
+ require_relative 'signatures/ffi_types'
2
+
3
+ module Logic
4
+ Signature = {
5
+ lua_to_ffi_types: Signatures::FFITypes,
6
+
7
+ to_ffi: ->(signature) {
8
+ result = [
9
+ signature[:name].to_sym,
10
+ signature[:input].map do |input|
11
+ input_type = Signature[:lua_to_ffi_types][input[:primitive].to_sym]
12
+
13
+ if input[:pointer]
14
+ :pointer
15
+ elsif input_type
16
+ input_type.to_sym
17
+ else
18
+ raise "missing primitive: #{input[:primitive]}"
19
+ end
20
+ end
21
+ ]
22
+
23
+ output_type = Signature[:lua_to_ffi_types][
24
+ signature[:output][:primitive].to_sym
25
+ ]
26
+
27
+ result << if signature[:output][:pointer]
28
+ :pointer
29
+ elsif output_type
30
+ output_type.to_sym
31
+ else
32
+ raise "missing primitive: #{signature[:output][:primitive]}"
33
+ end
34
+
35
+ result[1].pop while result[1].last == :void
36
+
37
+ result
38
+ },
39
+
40
+ extract_from_nm: ->(output) {
41
+ output.lines.map do |line|
42
+ line.sub(/\S+\s\S+\s/, '').strip
43
+ end.uniq.sort
44
+ },
45
+
46
+ remove_comments: ->(source) {
47
+ source.gsub(%r{/\*([\s\S]*?)\*/}, '')
48
+ },
49
+
50
+ extract_type_from_source: ->(source) {
51
+ sanitized_source = Signature[:sanitize_source_name].(source)
52
+
53
+ parts = sanitized_source
54
+ .gsub(/[{()].*/, '').gsub('*', '').gsub(/\s+/, ' ')
55
+ .strip.split(/\s/)
56
+
57
+ return nil if parts.size < 3
58
+
59
+ base_index = 1
60
+
61
+ if %w[unsigned signed const].include? parts[base_index].gsub(';', '')
62
+ base_index += 1
63
+ return nil if parts.size < 4
64
+ end
65
+
66
+ primitive = parts[base_index].gsub(';', '')
67
+ type = parts[base_index + 1].gsub(';', '')
68
+
69
+ { type: type, primitive: primitive }
70
+ },
71
+
72
+ extract_types_from_header: ->(source, types = {}) {
73
+ source = Signature[:remove_comments].(source)
74
+
75
+ # remove { ... }
76
+ source = source.gsub(/\{([\s\S]*?)\}/, '')
77
+
78
+ source.each_line do |line|
79
+ if line[/typedef/]
80
+ type = Signature[:extract_type_from_source].(line)
81
+ types[type[:type]] = type[:primitive] if type
82
+ end
83
+ end
84
+
85
+ types
86
+ },
87
+
88
+ extract_from_header: ->(source) {
89
+ source = Signature[:remove_comments].(source)
90
+
91
+ signatures = []
92
+
93
+ current_index = 0
94
+
95
+ source.each_line.with_index do |line, line_index|
96
+ next unless line_index > current_index - 1
97
+
98
+ line = line.strip
99
+
100
+ if line[/\w\)*\s*\(/] && !line[/typedef|^if\s/]
101
+ signature = line
102
+
103
+ current_index = line_index + 1
104
+
105
+ buffer = 100
106
+
107
+ while signature.scan(/\(/).size != signature.scan(/\)/).size &&
108
+ buffer.positive?
109
+
110
+ signature = "#{signature} #{source.lines[current_index]}"
111
+ current_index += 1
112
+
113
+ buffer -= 1
114
+ end
115
+
116
+ signature = signature.gsub(/\n/, ' ').gsub(/\s+/, ' ').strip
117
+
118
+ signatures << signature
119
+ end
120
+ end
121
+
122
+ signatures.uniq.sort
123
+ },
124
+
125
+ sanitize_source_name: ->(source) {
126
+ # int (*lorem) (lua_State *L, const void* p);
127
+ sanitized_source = source
128
+
129
+ candidate = sanitized_source[/\(\s*\**\s*\w+\s*\)\s*\(/]
130
+
131
+ if candidate
132
+ sanitized_source = sanitized_source.sub(
133
+ candidate, "#{candidate.gsub('(', '').gsub(')', '')}("
134
+ )
135
+ end
136
+
137
+ sanitized_source
138
+ },
139
+
140
+ is_macro?: ->(sanitized_source) {
141
+ function_source = sanitized_source.strip
142
+
143
+ if function_source[/^#define/] && function_source[/\)\s*\w*\(/]
144
+ function_source = function_source.gsub(/^#define\s*/, '')
145
+ function_source = function_source.sub(/\)\s*\w*\(.*/, ')')
146
+ return function_source
147
+ end
148
+
149
+ false
150
+ },
151
+
152
+ extract_macro_from_source: ->(function_source, sanitized_source) {
153
+ input = /\(([^()]+)\)/.match(sanitized_source)
154
+
155
+ input = if input
156
+ input[1].split(',').map(&:strip).map do |parameter|
157
+ Signature[:parse_parameter].(parameter, {})
158
+ end
159
+ else
160
+ []
161
+ end
162
+
163
+ function = {
164
+ name: sanitized_source.gsub(/\(.*/, '').strip,
165
+ macro: true,
166
+ input: input.map { |parameter| { name: parameter[:type] } },
167
+ source: function_source
168
+ }
169
+
170
+ function
171
+ },
172
+
173
+ extract_from_source: ->(function_source, types = {}) {
174
+ sanitized_source = Signature[:sanitize_source_name].(function_source)
175
+
176
+ macro = Signature[:is_macro?].(sanitized_source)
177
+
178
+ return Signature[:extract_macro_from_source].(function_source, macro) if macro
179
+
180
+ begin
181
+ input = /\(([^()]+)\)/
182
+ .match(sanitized_source)[1].split(',').map(&:strip)
183
+ .map do |parameter|
184
+ Signature[:parse_parameter].(parameter,
185
+ types)
186
+ end
187
+ rescue StandardError
188
+ return nil
189
+ end
190
+
191
+ function = Signature[:parse_function].(
192
+ sanitized_source.sub(/\(([^()]+)\)/, '').sub(';', '').strip, types
193
+ )
194
+
195
+ return nil if function.nil?
196
+
197
+ input.last[:name] = nil if input.last[:name] == '...'
198
+
199
+ if input.last[:type] == '...' || input.last[:name] == '...'
200
+ input.last[:type] = 'va_list'
201
+ input.last[:primitive] = 'va_list'
202
+ end
203
+
204
+ function[:input] = input
205
+ function[:source] = function_source
206
+
207
+ function
208
+ },
209
+
210
+ parse_parameter: ->(raw_parameter, types = {}) {
211
+ parts = raw_parameter.split(/\s+/)
212
+
213
+ parameter = { pointer: false, name: nil, type: nil, constant: false }
214
+
215
+ parts.each do |part|
216
+ parameter[:constant] = true if part.gsub('*', '').strip == 'const'
217
+
218
+ parameter[:pointer] = true if part[/\*/]
219
+ end
220
+
221
+ parts = parts.reject do |part|
222
+ part.gsub('*', '').strip == 'const'
223
+ end
224
+
225
+ parameter[:name] = parts.pop if parts.size > 1
226
+
227
+ parameter[:type] = parts.pop
228
+
229
+ parameter[:name] = parameter[:name].sub(/\*/, '') if parameter[:name]
230
+ parameter[:type] = parameter[:type].sub(/\*/, '') if parameter[:type]
231
+
232
+ parameter[:primitive] = parameter[:type]
233
+
234
+ budget = 10_000
235
+
236
+ if parameter[:primitive]
237
+ while types[parameter[:primitive]] && budget.positive?
238
+ parameter[:primitive] = types[parameter[:primitive]]
239
+ budget -= 1
240
+ end
241
+ end
242
+
243
+ warn "Fail to find primitive: #{parameter[:primitive]}" if budget.zero?
244
+
245
+ parameter
246
+ },
247
+
248
+ parse_function: ->(raw_function, types) {
249
+ output = Signature[:parse_parameter].(raw_function, types)
250
+
251
+ function_name = output.delete(:name)
252
+
253
+ return nil if function_name.nil? || output[:type].nil?
254
+
255
+ { name: function_name, output: output }
256
+ }
257
+ }
258
+ end
@@ -0,0 +1,27 @@
1
+ # https://github.com/ffi/ffi/wiki/Types#types
2
+
3
+ module Logic
4
+ module Signatures
5
+ FFITypes = {
6
+ char: 'char',
7
+ double: 'double',
8
+ int: 'int',
9
+ long: 'long',
10
+ LUA_INTEGER: 'int',
11
+ LUA_KCONTEXT: 'int',
12
+ LUA_NUMBER: 'double',
13
+ LUA_UNSIGNED: 'uint',
14
+ ptrdiff_t: 'int',
15
+ size_t: 'ulong',
16
+ va_list: 'varargs',
17
+ void: 'void',
18
+ enum: 'int', # TODO
19
+ struct: 'int', # TODO
20
+ TObject: 'int', # TODO
21
+
22
+ # Lua Jit:
23
+ short: 'int', # TODO
24
+ unsigned: 'int' # TODO
25
+ }
26
+ end
27
+ end