mt-lang 0.2.0

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.
Files changed (258) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/AUTHORS +3 -0
  4. data/Gemfile +19 -0
  5. data/Gemfile.lock +82 -0
  6. data/LICENSE +21 -0
  7. data/README.md +1208 -0
  8. data/Rakefile +332 -0
  9. data/bin/mtc +8 -0
  10. data/bin/profile-mtc-checks +133 -0
  11. data/bin/tracy-profiler +0 -0
  12. data/docs/build-guide.md +536 -0
  13. data/docs/index.html +2778 -0
  14. data/docs/language-design.md +1519 -0
  15. data/docs/language-manual.md +1534 -0
  16. data/lib/milk_tea/base.rb +49 -0
  17. data/lib/milk_tea/bindings/bindgen/ast_parser.rb +398 -0
  18. data/lib/milk_tea/bindings/bindgen/declaration.rb +319 -0
  19. data/lib/milk_tea/bindings/bindgen/emitter.rb +387 -0
  20. data/lib/milk_tea/bindings/bindgen/overrides.rb +134 -0
  21. data/lib/milk_tea/bindings/bindgen/type_mapper.rb +622 -0
  22. data/lib/milk_tea/bindings/bindgen.rb +207 -0
  23. data/lib/milk_tea/bindings/cli.rb +121 -0
  24. data/lib/milk_tea/bindings/imported_bindings/defaults.rb +210 -0
  25. data/lib/milk_tea/bindings/imported_bindings/generator.rb +1114 -0
  26. data/lib/milk_tea/bindings/imported_bindings/method_source.rb +190 -0
  27. data/lib/milk_tea/bindings/imported_bindings/naming.rb +286 -0
  28. data/lib/milk_tea/bindings/imported_bindings.rb +215 -0
  29. data/lib/milk_tea/bindings/opengl_registry.rb +547 -0
  30. data/lib/milk_tea/bindings/raw_bindings/defaults.rb +1338 -0
  31. data/lib/milk_tea/bindings/raw_bindings.rb +269 -0
  32. data/lib/milk_tea/bindings/steamworks.rb +629 -0
  33. data/lib/milk_tea/bindings/upstream_sources.rb +352 -0
  34. data/lib/milk_tea/bindings/vendored_box2d.rb +79 -0
  35. data/lib/milk_tea/bindings/vendored_c_library.rb +322 -0
  36. data/lib/milk_tea/bindings/vendored_cjson.rb +52 -0
  37. data/lib/milk_tea/bindings/vendored_flecs.rb +78 -0
  38. data/lib/milk_tea/bindings/vendored_glfw.rb +77 -0
  39. data/lib/milk_tea/bindings/vendored_libuv.rb +75 -0
  40. data/lib/milk_tea/bindings/vendored_pcre2.rb +84 -0
  41. data/lib/milk_tea/bindings/vendored_raylib.rb +131 -0
  42. data/lib/milk_tea/bindings/vendored_sdl3.rb +78 -0
  43. data/lib/milk_tea/bindings/vendored_steamworks.rb +71 -0
  44. data/lib/milk_tea/bindings/vendored_tool.rb +71 -0
  45. data/lib/milk_tea/bindings/vendored_tools.rb +23 -0
  46. data/lib/milk_tea/bindings/vendored_tracy.rb +37 -0
  47. data/lib/milk_tea/bindings.rb +23 -0
  48. data/lib/milk_tea/core/ast.rb +311 -0
  49. data/lib/milk_tea/core/async_runtime_installer.rb +28 -0
  50. data/lib/milk_tea/core/binding_types.rb +18 -0
  51. data/lib/milk_tea/core/bindings/attribute_binding.rb +58 -0
  52. data/lib/milk_tea/core/bindings/function_binding.rb +5 -0
  53. data/lib/milk_tea/core/bindings/module_binding.rb +58 -0
  54. data/lib/milk_tea/core/bindings/value_binding.rb +21 -0
  55. data/lib/milk_tea/core/c_backend/aggregate_utils.rb +103 -0
  56. data/lib/milk_tea/core/c_backend/control_flow_emission.rb +412 -0
  57. data/lib/milk_tea/core/c_backend/expressions.rb +468 -0
  58. data/lib/milk_tea/core/c_backend/feature_detection.rb +483 -0
  59. data/lib/milk_tea/core/c_backend/reachability.rb +398 -0
  60. data/lib/milk_tea/core/c_backend/reinterpret.rb +226 -0
  61. data/lib/milk_tea/core/c_backend/runtime_helpers.rb +1080 -0
  62. data/lib/milk_tea/core/c_backend/statements.rb +563 -0
  63. data/lib/milk_tea/core/c_backend/type_collectors.rb +1545 -0
  64. data/lib/milk_tea/core/c_backend/type_declaration.rb +223 -0
  65. data/lib/milk_tea/core/c_backend/type_system.rb +345 -0
  66. data/lib/milk_tea/core/c_backend.rb +287 -0
  67. data/lib/milk_tea/core/compatibility_helpers.rb +79 -0
  68. data/lib/milk_tea/core/compile_time/const_eval.rb +187 -0
  69. data/lib/milk_tea/core/compile_time.rb +329 -0
  70. data/lib/milk_tea/core/control_flow/builder.rb +582 -0
  71. data/lib/milk_tea/core/control_flow/constant_propagation.rb +143 -0
  72. data/lib/milk_tea/core/control_flow/dataflow.rb +74 -0
  73. data/lib/milk_tea/core/control_flow/definite_assignment.rb +79 -0
  74. data/lib/milk_tea/core/control_flow/graph.rb +90 -0
  75. data/lib/milk_tea/core/control_flow/liveness.rb +24 -0
  76. data/lib/milk_tea/core/control_flow/nullability_flow.rb +43 -0
  77. data/lib/milk_tea/core/control_flow/reachability.rb +22 -0
  78. data/lib/milk_tea/core/control_flow/termination.rb +31 -0
  79. data/lib/milk_tea/core/control_flow.rb +34 -0
  80. data/lib/milk_tea/core/cst.rb +48 -0
  81. data/lib/milk_tea/core/cst_builder.rb +19 -0
  82. data/lib/milk_tea/core/ir.rb +85 -0
  83. data/lib/milk_tea/core/keywords.rb +97 -0
  84. data/lib/milk_tea/core/lexer/character_classes.rb +60 -0
  85. data/lib/milk_tea/core/lexer/format_strings.rb +225 -0
  86. data/lib/milk_tea/core/lexer/heredocs.rb +199 -0
  87. data/lib/milk_tea/core/lexer/indentation.rb +62 -0
  88. data/lib/milk_tea/core/lexer/numbers.rb +96 -0
  89. data/lib/milk_tea/core/lexer/recovery.rb +32 -0
  90. data/lib/milk_tea/core/lexer/strings.rb +167 -0
  91. data/lib/milk_tea/core/lexer/symbols.rb +71 -0
  92. data/lib/milk_tea/core/lexer/trivia.rb +53 -0
  93. data/lib/milk_tea/core/lexer.rb +430 -0
  94. data/lib/milk_tea/core/lowering/artifacts.rb +26 -0
  95. data/lib/milk_tea/core/lowering/async/analysis.rb +245 -0
  96. data/lib/milk_tea/core/lowering/async/lowering.rb +1399 -0
  97. data/lib/milk_tea/core/lowering/async/normalization.rb +459 -0
  98. data/lib/milk_tea/core/lowering/async.rb +714 -0
  99. data/lib/milk_tea/core/lowering/block.rb +1052 -0
  100. data/lib/milk_tea/core/lowering/calls.rb +1565 -0
  101. data/lib/milk_tea/core/lowering/declarations.rb +214 -0
  102. data/lib/milk_tea/core/lowering/dyn.rb +206 -0
  103. data/lib/milk_tea/core/lowering/events.rb +1054 -0
  104. data/lib/milk_tea/core/lowering/expressions.rb +1645 -0
  105. data/lib/milk_tea/core/lowering/foreign_cstr.rb +206 -0
  106. data/lib/milk_tea/core/lowering/functions.rb +242 -0
  107. data/lib/milk_tea/core/lowering/loops.rb +1087 -0
  108. data/lib/milk_tea/core/lowering/lowering_context.rb +80 -0
  109. data/lib/milk_tea/core/lowering/proc.rb +419 -0
  110. data/lib/milk_tea/core/lowering/resolve.rb +2516 -0
  111. data/lib/milk_tea/core/lowering/scans.rb +220 -0
  112. data/lib/milk_tea/core/lowering/str_buffer.rb +125 -0
  113. data/lib/milk_tea/core/lowering/utils.rb +1453 -0
  114. data/lib/milk_tea/core/lowering.rb +378 -0
  115. data/lib/milk_tea/core/module_binder.rb +181 -0
  116. data/lib/milk_tea/core/module_loader/errors.rb +21 -0
  117. data/lib/milk_tea/core/module_loader.rb +479 -0
  118. data/lib/milk_tea/core/module_path_resolver.rb +153 -0
  119. data/lib/milk_tea/core/module_roots.rb +88 -0
  120. data/lib/milk_tea/core/parser/attributes.rb +71 -0
  121. data/lib/milk_tea/core/parser/blocks.rb +119 -0
  122. data/lib/milk_tea/core/parser/declarations.rb +749 -0
  123. data/lib/milk_tea/core/parser/expressions.rb +624 -0
  124. data/lib/milk_tea/core/parser/recovery.rb +131 -0
  125. data/lib/milk_tea/core/parser/statements.rb +756 -0
  126. data/lib/milk_tea/core/parser/types.rb +271 -0
  127. data/lib/milk_tea/core/parser.rb +400 -0
  128. data/lib/milk_tea/core/prelude_installer.rb +29 -0
  129. data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +917 -0
  130. data/lib/milk_tea/core/pretty_printer/base_formatter.rb +87 -0
  131. data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +300 -0
  132. data/lib/milk_tea/core/pretty_printer.rb +17 -0
  133. data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +314 -0
  134. data/lib/milk_tea/core/semantic_analyzer/attributes.rb +184 -0
  135. data/lib/milk_tea/core/semantic_analyzer/calls.rb +992 -0
  136. data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1735 -0
  137. data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +355 -0
  138. data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +155 -0
  139. data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +354 -0
  140. data/lib/milk_tea/core/semantic_analyzer/generics.rb +383 -0
  141. data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +78 -0
  142. data/lib/milk_tea/core/semantic_analyzer/module_context.rb +35 -0
  143. data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +1438 -0
  144. data/lib/milk_tea/core/semantic_analyzer/nullability.rb +421 -0
  145. data/lib/milk_tea/core/semantic_analyzer/statements.rb +1308 -0
  146. data/lib/milk_tea/core/semantic_analyzer/top_level.rb +588 -0
  147. data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +307 -0
  148. data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +851 -0
  149. data/lib/milk_tea/core/semantic_analyzer.rb +327 -0
  150. data/lib/milk_tea/core/token.rb +26 -0
  151. data/lib/milk_tea/core/token_stream.rb +30 -0
  152. data/lib/milk_tea/core/types/layout.rb +243 -0
  153. data/lib/milk_tea/core/types/predicates.rb +609 -0
  154. data/lib/milk_tea/core/types/registry.rb +83 -0
  155. data/lib/milk_tea/core/types/types.rb +1696 -0
  156. data/lib/milk_tea/core/types/visitor.rb +442 -0
  157. data/lib/milk_tea/core.rb +25 -0
  158. data/lib/milk_tea/dap/backends/lldb_dap.rb +158 -0
  159. data/lib/milk_tea/dap/protocol.rb +58 -0
  160. data/lib/milk_tea/dap/server/breakpoints.rb +66 -0
  161. data/lib/milk_tea/dap/server/debug_map.rb +291 -0
  162. data/lib/milk_tea/dap/server/handlers.rb +374 -0
  163. data/lib/milk_tea/dap/server/launch.rb +261 -0
  164. data/lib/milk_tea/dap/server/lldb_backend.rb +380 -0
  165. data/lib/milk_tea/dap/server/pause_diagnostics.rb +109 -0
  166. data/lib/milk_tea/dap/server/utilities.rb +160 -0
  167. data/lib/milk_tea/dap/server/wire.rb +55 -0
  168. data/lib/milk_tea/dap/server.rb +131 -0
  169. data/lib/milk_tea/dap/session.rb +152 -0
  170. data/lib/milk_tea/dap.rb +6 -0
  171. data/lib/milk_tea/lsp/dependency_resolution.rb +52 -0
  172. data/lib/milk_tea/lsp/diagnostics.rb +611 -0
  173. data/lib/milk_tea/lsp/protocol.rb +104 -0
  174. data/lib/milk_tea/lsp/server/call_hierarchy.rb +274 -0
  175. data/lib/milk_tea/lsp/server/code_actions.rb +446 -0
  176. data/lib/milk_tea/lsp/server/code_lens.rb +97 -0
  177. data/lib/milk_tea/lsp/server/completion.rb +1099 -0
  178. data/lib/milk_tea/lsp/server/configuration.rb +167 -0
  179. data/lib/milk_tea/lsp/server/debug_info.rb +45 -0
  180. data/lib/milk_tea/lsp/server/definition.rb +779 -0
  181. data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +239 -0
  182. data/lib/milk_tea/lsp/server/execute_command.rb +25 -0
  183. data/lib/milk_tea/lsp/server/folding_range.rb +153 -0
  184. data/lib/milk_tea/lsp/server/formatting.rb +575 -0
  185. data/lib/milk_tea/lsp/server/hover.rb +1465 -0
  186. data/lib/milk_tea/lsp/server/inlay_hints.rb +204 -0
  187. data/lib/milk_tea/lsp/server/lifecycle.rb +234 -0
  188. data/lib/milk_tea/lsp/server/linked_editing_range.rb +43 -0
  189. data/lib/milk_tea/lsp/server/on_type_formatting.rb +73 -0
  190. data/lib/milk_tea/lsp/server/progress.rb +47 -0
  191. data/lib/milk_tea/lsp/server/references.rb +433 -0
  192. data/lib/milk_tea/lsp/server/rename.rb +598 -0
  193. data/lib/milk_tea/lsp/server/selection_range.rb +130 -0
  194. data/lib/milk_tea/lsp/server/semantic_tokens.rb +1745 -0
  195. data/lib/milk_tea/lsp/server/signature_help.rb +200 -0
  196. data/lib/milk_tea/lsp/server/text_documents.rb +125 -0
  197. data/lib/milk_tea/lsp/server/type_hierarchy.rb +167 -0
  198. data/lib/milk_tea/lsp/server/utilities.rb +520 -0
  199. data/lib/milk_tea/lsp/server.rb +415 -0
  200. data/lib/milk_tea/lsp/workspace/analysis.rb +209 -0
  201. data/lib/milk_tea/lsp/workspace/caches.rb +260 -0
  202. data/lib/milk_tea/lsp/workspace/collection.rb +98 -0
  203. data/lib/milk_tea/lsp/workspace/definition_index.rb +184 -0
  204. data/lib/milk_tea/lsp/workspace/dependency_graph.rb +282 -0
  205. data/lib/milk_tea/lsp/workspace/store.rb +154 -0
  206. data/lib/milk_tea/lsp/workspace/utilities.rb +490 -0
  207. data/lib/milk_tea/lsp/workspace.rb +127 -0
  208. data/lib/milk_tea/lsp.rb +13 -0
  209. data/lib/milk_tea/packages/atomic_write.rb +63 -0
  210. data/lib/milk_tea/packages/dependency_solver.rb +194 -0
  211. data/lib/milk_tea/packages/graph.rb +139 -0
  212. data/lib/milk_tea/packages/lock.rb +421 -0
  213. data/lib/milk_tea/packages/manager_cli.rb +485 -0
  214. data/lib/milk_tea/packages/manifest.rb +356 -0
  215. data/lib/milk_tea/packages/manifest_editor.rb +134 -0
  216. data/lib/milk_tea/packages/registry_metadata_provider.rb +34 -0
  217. data/lib/milk_tea/packages/registry_store.rb +420 -0
  218. data/lib/milk_tea/packages/services.rb +41 -0
  219. data/lib/milk_tea/packages/source_cache.rb +71 -0
  220. data/lib/milk_tea/packages/source_fetcher.rb +124 -0
  221. data/lib/milk_tea/packages/source_resolver.rb +389 -0
  222. data/lib/milk_tea/packages/version.rb +164 -0
  223. data/lib/milk_tea/packages.rb +16 -0
  224. data/lib/milk_tea/tooling/asset_pack.rb +141 -0
  225. data/lib/milk_tea/tooling/build.rb +1124 -0
  226. data/lib/milk_tea/tooling/build_cache.rb +240 -0
  227. data/lib/milk_tea/tooling/cli.rb +2688 -0
  228. data/lib/milk_tea/tooling/cst_formatter.rb +13 -0
  229. data/lib/milk_tea/tooling/debug_info_formatter.rb +456 -0
  230. data/lib/milk_tea/tooling/debug_map.rb +248 -0
  231. data/lib/milk_tea/tooling/docs_app.rb +369 -0
  232. data/lib/milk_tea/tooling/error_formatter.rb +86 -0
  233. data/lib/milk_tea/tooling/formatter.rb +787 -0
  234. data/lib/milk_tea/tooling/linter/doc_tags.rb +212 -0
  235. data/lib/milk_tea/tooling/linter/fix_engine.rb +237 -0
  236. data/lib/milk_tea/tooling/linter/flow_rules.rb +380 -0
  237. data/lib/milk_tea/tooling/linter/imports_platform.rb +841 -0
  238. data/lib/milk_tea/tooling/linter/release_rules.rb +744 -0
  239. data/lib/milk_tea/tooling/linter/reserved_names.rb +199 -0
  240. data/lib/milk_tea/tooling/linter/rules.rb +593 -0
  241. data/lib/milk_tea/tooling/linter/source_helpers.rb +407 -0
  242. data/lib/milk_tea/tooling/linter/trailing_comma.rb +139 -0
  243. data/lib/milk_tea/tooling/linter/visitors.rb +1286 -0
  244. data/lib/milk_tea/tooling/linter.rb +798 -0
  245. data/lib/milk_tea/tooling/project_scaffold.rb +82 -0
  246. data/lib/milk_tea/tooling/public/css/docs.css +166 -0
  247. data/lib/milk_tea/tooling/public/js/docs.js +94 -0
  248. data/lib/milk_tea/tooling/run.rb +408 -0
  249. data/lib/milk_tea/tooling/templates/wasm_shell.html +48 -0
  250. data/lib/milk_tea/tooling/toolchain_cli.rb +157 -0
  251. data/lib/milk_tea/tooling/views/404.erb +7 -0
  252. data/lib/milk_tea/tooling/views/index.erb +87 -0
  253. data/lib/milk_tea/tooling/views/layout.erb +69 -0
  254. data/lib/milk_tea/tooling/views/module.erb +97 -0
  255. data/lib/milk_tea/tooling/views/stdlib.erb +21 -0
  256. data/lib/milk_tea/tooling.rb +20 -0
  257. data/lib/milk_tea.rb +8 -0
  258. metadata +426 -0
@@ -0,0 +1,269 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module MilkTea
6
+ module RawBindings
7
+ class Error < StandardError; end
8
+
9
+ class Binding
10
+ attr_reader :name, :module_name, :binding_path, :include_directives, :bindgen_defines, :bindgen_include_directives, :module_imports, :link_libraries, :header_candidates, :tracked_header_paths, :tracked_header_prefixes, :declaration_name_prefixes, :excluded_declaration_names, :env_var, :clang_args, :compiler_flags, :implementation_defines, :type_name_overrides, :type_overrides, :function_param_type_overrides, :function_return_type_overrides, :field_type_overrides, :vendored_library, :strip_leading_underscores
11
+
12
+ def initialize(name:, module_name:, binding_path:, header_candidates:, tracked_header_paths: [], tracked_header_prefixes: [], declaration_name_prefixes: [], excluded_declaration_names: [], include_directives: nil, bindgen_defines: [], bindgen_include_directives: [], module_imports: [], link_libraries: [], link_flags: [], env_var: nil, clang: nil, clang_args: [], compiler_flags: [], implementation_defines: [], type_name_overrides: {}, type_overrides: {}, function_param_type_overrides: {}, function_return_type_overrides: {}, field_type_overrides: {}, vendored_library: nil, prepare: nil, generator: nil, allow_static_inline_functions: false, strip_leading_underscores: false)
13
+ @name = name.to_s
14
+ @module_name = module_name
15
+ @binding_path = File.expand_path(binding_path.to_s)
16
+ @header_candidates = header_candidates.map { |path| File.expand_path(path) }.freeze
17
+ @tracked_header_paths = tracked_header_paths.map { |path| File.expand_path(path) }.freeze
18
+ @tracked_header_prefixes = tracked_header_prefixes.map { |path| File.expand_path(path) }.freeze
19
+ @declaration_name_prefixes = declaration_name_prefixes.dup.freeze
20
+ @excluded_declaration_names = excluded_declaration_names.map(&:to_s).freeze
21
+ @include_directives = include_directives&.dup&.freeze
22
+ @bindgen_defines = bindgen_defines.dup.freeze
23
+ @bindgen_include_directives = bindgen_include_directives.dup.freeze
24
+ @link_libraries = link_libraries.dup.freeze
25
+ @link_flags = link_flags.dup.freeze
26
+ @env_var = env_var
27
+ @clang = clang
28
+ @clang_args = clang_args.dup.freeze
29
+ @compiler_flags = compiler_flags.dup.freeze
30
+ @implementation_defines = implementation_defines.dup.freeze
31
+ @module_imports = module_imports.dup.freeze
32
+ @type_name_overrides = type_name_overrides.transform_keys(&:to_s).transform_values(&:to_s).freeze
33
+ @type_overrides = type_overrides.transform_keys(&:to_s).freeze
34
+ @function_param_type_overrides = normalize_function_param_type_overrides(function_param_type_overrides)
35
+ @function_return_type_overrides = function_return_type_overrides.transform_keys(&:to_s).freeze
36
+ @field_type_overrides = normalize_field_type_overrides(field_type_overrides)
37
+ @vendored_library = vendored_library
38
+ @prepare = prepare
39
+ @generator = generator
40
+ @allow_static_inline_functions = allow_static_inline_functions
41
+ @strip_leading_underscores = strip_leading_underscores
42
+ end
43
+
44
+ def task_name
45
+ "bindgen:#{name}"
46
+ end
47
+
48
+ def check_task_name
49
+ "bindgen:check:#{name}"
50
+ end
51
+
52
+ def legacy_check_task_name
53
+ "bindgen:check_#{name}"
54
+ end
55
+
56
+ def header_label
57
+ return include_directives.first if include_directives && !include_directives.empty?
58
+ return File.basename(header_candidates.first) unless header_candidates.empty?
59
+
60
+ name
61
+ end
62
+
63
+ def link_flags(platform: nil)
64
+ flags = []
65
+ flags.concat(vendored_library.link_flags(platform:)) if vendored_library
66
+ flags.concat(@link_flags)
67
+ flags.uniq
68
+ end
69
+
70
+ def header_path(env: ENV)
71
+ candidates = []
72
+ override = env_var && env[env_var]
73
+ candidates << override unless override.nil? || override.empty?
74
+ candidates.concat(header_candidates)
75
+
76
+ resolved = candidates.find { |path| File.file?(path) }
77
+ return resolved if resolved
78
+
79
+ if env_var
80
+ raise Error, "#{header_label} header not found; set #{env_var} or install #{header_label} headers"
81
+ end
82
+
83
+ raise Error, "#{header_label} header not found"
84
+ end
85
+
86
+ def generate(env: ENV, header_path: nil)
87
+ resolved_header_path = header_path || self.header_path(env:)
88
+ return @generator.call(self, env:, header_path: resolved_header_path) if @generator
89
+
90
+ MilkTea::Bindgen.generate(**bindgen_kwargs(env:, header_path: resolved_header_path))
91
+ end
92
+
93
+ def nullable_policy_report(env: ENV, header_path: nil)
94
+ resolved_header_path = header_path || self.header_path(env:)
95
+ raise Error, "nullable policy report unavailable for custom raw binding generator #{name}" if @generator
96
+
97
+ MilkTea::Bindgen.generate_with_report(**bindgen_kwargs(env:, header_path: resolved_header_path)).fetch(:nullable_policy_report)
98
+ end
99
+
100
+ def nullable_policy_report_path(root: MilkTea.root)
101
+ File.expand_path(File.join(root, "tmp", "bindgen-nullable-reports", "#{name}.json"))
102
+ end
103
+
104
+ def write_nullable_policy_report!(env: ENV, header_path: nil, output_path: nil)
105
+ resolved_header_path = header_path || self.header_path(env:)
106
+ report_path = File.expand_path(output_path || nullable_policy_report_path)
107
+ FileUtils.mkdir_p(File.dirname(report_path))
108
+ if @generator
109
+ File.write(report_path, JSON.pretty_generate({}))
110
+ else
111
+ File.write(report_path, JSON.pretty_generate(nullable_policy_report(env:, header_path: resolved_header_path)))
112
+ end
113
+ report_path
114
+ end
115
+
116
+ def build_flags(env: ENV, header_path: nil, platform: nil)
117
+ resolved_header_path = header_path || self.header_path(env:)
118
+ include_dir = File.dirname(resolved_header_path)
119
+ flags = []
120
+ flags << "-I#{include_dir}" unless include_dir.nil? || include_dir.empty?
121
+ implementation_defines.each do |define|
122
+ flags << "-D#{define}"
123
+ end
124
+ flags.concat(compiler_flags)
125
+ flags.concat(vendored_library.build_flags(platform:)) if vendored_library&.respond_to?(:build_flags)
126
+ flags.uniq
127
+ end
128
+
129
+ def write!(env: ENV)
130
+ prepare!(env:, cc: env.fetch("CC", "cc"))
131
+ resolved_header_path = header_path(env:)
132
+ File.write(binding_path, generate(env:, header_path: resolved_header_path))
133
+ resolved_header_path
134
+ end
135
+
136
+ def check!(env: ENV)
137
+ prepare!(env:, cc: env.fetch("CC", "cc"))
138
+ resolved_header_path = header_path(env:)
139
+ expected = normalized_output(File.read(binding_path))
140
+ actual = normalized_output(generate(env:, header_path: resolved_header_path))
141
+
142
+ if expected != actual
143
+ raise Error, <<~MESSAGE
144
+ #{binding_path} is out of date for #{resolved_header_path}
145
+ Run `rake #{task_name}` to regenerate it.
146
+ MESSAGE
147
+ end
148
+
149
+ MilkTea::ModuleLoader.check_file(binding_path)
150
+ resolved_header_path
151
+ end
152
+
153
+ def prepare!(env: ENV, cc: ENV.fetch("CC", "cc"), platform: nil)
154
+ if @prepare
155
+ kwargs = { env:, cc: }
156
+ kwargs[:platform] = platform if prepare_accepts_keyword?(:platform)
157
+ @prepare.call(self, **kwargs)
158
+ end
159
+ vendored_library&.prepare!(env:, cc:, platform:)
160
+ end
161
+
162
+ private
163
+
164
+ def normalize_function_param_type_overrides(overrides)
165
+ overrides.each_with_object({}) do |(function_name, param_overrides), normalized|
166
+ normalized[function_name.to_s] = param_overrides.each_with_object({}) do |(param_name, type), params|
167
+ params[param_name.to_s] = type.to_s
168
+ end.freeze
169
+ end.freeze
170
+ end
171
+
172
+ def normalize_field_type_overrides(overrides)
173
+ overrides.each_with_object({}) do |(type_name, field_overrides), normalized|
174
+ normalized[type_name.to_s] = field_overrides.each_with_object({}) do |(field_name, type), fields|
175
+ fields[field_name.to_s] = type.to_s
176
+ end.freeze
177
+ end.freeze
178
+ end
179
+
180
+ def resolved_clang(env)
181
+ @clang || env.fetch("CLANG", "clang")
182
+ end
183
+
184
+ def bindgen_kwargs(env:, header_path:)
185
+ kwargs = {
186
+ module_name:,
187
+ header_path:,
188
+ link_libraries:,
189
+ include_directives:,
190
+ bindgen_defines:,
191
+ bindgen_include_directives:,
192
+ module_imports:,
193
+ clang: resolved_clang(env),
194
+ clang_args:,
195
+ type_name_overrides:,
196
+ type_overrides:,
197
+ function_param_type_overrides:,
198
+ function_return_type_overrides:,
199
+ field_type_overrides:,
200
+ }
201
+ kwargs[:tracked_header_paths] = tracked_header_paths unless tracked_header_paths.empty?
202
+ kwargs[:tracked_header_prefixes] = tracked_header_prefixes unless tracked_header_prefixes.empty?
203
+ kwargs[:declaration_name_prefixes] = declaration_name_prefixes unless declaration_name_prefixes.empty?
204
+ kwargs[:excluded_declaration_names] = excluded_declaration_names unless excluded_declaration_names.empty?
205
+ kwargs[:allow_static_inline_functions] = true if @allow_static_inline_functions
206
+ kwargs[:strip_leading_underscores] = true if @strip_leading_underscores
207
+ kwargs
208
+ end
209
+
210
+ def prepare_accepts_keyword?(keyword)
211
+ @prepare.parameters.any? do |kind, name|
212
+ kind == :keyrest || ((kind == :key || kind == :keyreq) && name == keyword)
213
+ end
214
+ end
215
+
216
+ def normalized_output(source)
217
+ source.sub(/\A# generated by mtc bindgen from .*\n/, "# generated by mtc bindgen from <header>\n")
218
+ end
219
+ end
220
+
221
+ class Registry
222
+ include Enumerable
223
+
224
+ def initialize(bindings = [])
225
+ @bindings = {}
226
+ @bindings_by_module_name = {}
227
+ bindings.each { |binding| register(binding) }
228
+ end
229
+
230
+ def register(binding)
231
+ raise Error, "duplicate raw binding #{binding.name}" if @bindings.key?(binding.name)
232
+ raise Error, "duplicate raw binding module #{binding.module_name}" if @bindings_by_module_name.key?(binding.module_name)
233
+
234
+ @bindings[binding.name] = binding
235
+ @bindings_by_module_name[binding.module_name] = binding
236
+ end
237
+
238
+ def fetch(name)
239
+ @bindings.fetch(name.to_s)
240
+ rescue KeyError
241
+ raise Error, "unknown raw binding #{name}"
242
+ end
243
+
244
+ def each(&block)
245
+ @bindings.each_value(&block)
246
+ end
247
+
248
+ def find_by_module_name(module_name)
249
+ @bindings_by_module_name[module_name]
250
+ end
251
+
252
+ def task_names
253
+ map(&:task_name)
254
+ end
255
+
256
+ def check_task_names
257
+ map(&:check_task_name)
258
+ end
259
+ end
260
+
261
+ require_relative "raw_bindings/defaults"
262
+
263
+ def self.default_registry(root: MilkTea.root)
264
+ registry = Registry.new
265
+ default_bindings(root:).each { |binding| registry.register(binding) }
266
+ registry
267
+ end
268
+ end
269
+ end