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,207 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "open3"
5
+ require "tempfile"
6
+ require_relative "../tooling/formatter"
7
+ require_relative "../core/token"
8
+ require_relative "../core/types/types"
9
+ require_relative "bindgen/ast_parser"
10
+ require_relative "bindgen/declaration"
11
+ require_relative "bindgen/type_mapper"
12
+ require_relative "bindgen/emitter"
13
+ require_relative "bindgen/overrides"
14
+
15
+ module MilkTea
16
+ module Bindgen
17
+ MACRO_CONST_PREFIX = "__mt_bindgen_macro_"
18
+ QUALIFIERS = %w[const volatile restrict].freeze
19
+ NULLABILITY_QUALIFIERS = %w[_Nullable _Nonnull _Null_unspecified _Nullable_result].freeze
20
+ NON_VALUE_MACRO_TOKENS = %w[
21
+ extern static inline typedef struct union enum do if else for while return sizeof
22
+ __attribute__ __attribute __declspec
23
+ ].freeze
24
+ PRIMITIVE_TYPE_MAP = {
25
+ "_Bool" => "bool",
26
+ "bool" => "bool",
27
+ "void" => "void",
28
+ "char" => "char",
29
+ "signed char" => "byte",
30
+ "unsigned char" => "ubyte",
31
+ "short" => "short",
32
+ "short int" => "short",
33
+ "signed short" => "short",
34
+ "signed short int" => "short",
35
+ "unsigned short" => "ushort",
36
+ "unsigned short int" => "ushort",
37
+ "int" => "int",
38
+ "signed" => "int",
39
+ "signed int" => "int",
40
+ "unsigned" => "uint",
41
+ "unsigned int" => "uint",
42
+ "long" => "ptr_int",
43
+ "long int" => "ptr_int",
44
+ "signed long" => "ptr_int",
45
+ "signed long int" => "ptr_int",
46
+ "unsigned long" => "ptr_uint",
47
+ "unsigned long int" => "ptr_uint",
48
+ "long long" => "long",
49
+ "long long int" => "long",
50
+ "signed long long" => "long",
51
+ "signed long long int" => "long",
52
+ "unsigned long long" => "ulong",
53
+ "unsigned long long int" => "ulong",
54
+ "float" => "float",
55
+ "double" => "double",
56
+ }.freeze
57
+
58
+ def self.generate(module_name:, header_path:, tracked_header_paths: [], tracked_header_prefixes: [], declaration_name_prefixes: [], excluded_declaration_names: [], link_libraries: [], include_directives: nil, bindgen_defines: [], bindgen_include_directives: [], module_imports: [], clang: ENV.fetch("CLANG", "clang"), clang_args: [], type_name_overrides: {}, type_overrides: {}, function_param_type_overrides: {}, function_return_type_overrides: {}, field_type_overrides: {}, allow_static_inline_functions: false, strip_leading_underscores: false)
59
+ generate_with_report(
60
+ module_name:,
61
+ header_path:,
62
+ tracked_header_paths:,
63
+ tracked_header_prefixes:,
64
+ declaration_name_prefixes:,
65
+ excluded_declaration_names:,
66
+ link_libraries:,
67
+ include_directives:,
68
+ bindgen_defines:,
69
+ bindgen_include_directives:,
70
+ module_imports:,
71
+ clang:,
72
+ clang_args:,
73
+ type_name_overrides:,
74
+ type_overrides:,
75
+ function_param_type_overrides:,
76
+ function_return_type_overrides:,
77
+ field_type_overrides:,
78
+ allow_static_inline_functions:,
79
+ strip_leading_underscores:,
80
+ ).fetch(:source)
81
+ end
82
+
83
+ def self.generate_with_report(module_name:, header_path:, tracked_header_paths: [], tracked_header_prefixes: [], declaration_name_prefixes: [], excluded_declaration_names: [], link_libraries: [], include_directives: nil, bindgen_defines: [], bindgen_include_directives: [], module_imports: [], clang: ENV.fetch("CLANG", "clang"), clang_args: [], type_name_overrides: {}, type_overrides: {}, function_param_type_overrides: {}, function_return_type_overrides: {}, field_type_overrides: {}, allow_static_inline_functions: false, strip_leading_underscores: false)
84
+ Generator.new(
85
+ module_name:,
86
+ header_path:,
87
+ tracked_header_paths:,
88
+ tracked_header_prefixes:,
89
+ declaration_name_prefixes:,
90
+ excluded_declaration_names:,
91
+ link_libraries:,
92
+ include_directives:,
93
+ bindgen_defines:,
94
+ bindgen_include_directives:,
95
+ module_imports:,
96
+ clang:,
97
+ clang_args:,
98
+ type_name_overrides:,
99
+ type_overrides:,
100
+ function_param_type_overrides:,
101
+ function_return_type_overrides:,
102
+ field_type_overrides:,
103
+ allow_static_inline_functions:,
104
+ strip_leading_underscores:,
105
+ ).generate_with_report
106
+ end
107
+
108
+ class Generator
109
+ def initialize(module_name:, header_path:, tracked_header_paths:, tracked_header_prefixes:, declaration_name_prefixes:, excluded_declaration_names:, link_libraries:, include_directives:, bindgen_defines:, bindgen_include_directives:, module_imports:, clang:, clang_args:, type_name_overrides:, type_overrides:, function_param_type_overrides:, function_return_type_overrides:, field_type_overrides:, allow_static_inline_functions:, strip_leading_underscores: false)
110
+ @module_name = module_name
111
+ @header_path = File.expand_path(header_path)
112
+ @tracked_header_paths = ([header_path] + tracked_header_paths).map { |path| File.expand_path(path) }.uniq.freeze
113
+ @tracked_header_prefixes = tracked_header_prefixes.map { |path| File.expand_path(path) }.uniq.freeze
114
+ @declaration_name_prefixes = declaration_name_prefixes.dup.freeze
115
+ @excluded_declaration_names = excluded_declaration_names.map(&:to_s).freeze
116
+ @link_libraries = link_libraries.dup
117
+ @include_directives = include_directives&.dup
118
+ @bindgen_defines = bindgen_defines.dup.freeze
119
+ @bindgen_include_directives = bindgen_include_directives.dup.freeze
120
+ @module_imports = normalize_module_imports(module_imports)
121
+ @clang = clang
122
+ @clang_args = clang_args.dup
123
+ @type_name_overrides = normalize_type_name_overrides(type_name_overrides)
124
+ @type_overrides = normalize_type_overrides(type_overrides)
125
+ @function_param_type_overrides = normalize_function_param_type_overrides(function_param_type_overrides)
126
+ @function_return_type_overrides = normalize_function_return_type_overrides(function_return_type_overrides)
127
+ @field_type_overrides = normalize_field_type_overrides(field_type_overrides)
128
+ @allow_static_inline_functions = allow_static_inline_functions
129
+ @strip_leading_underscores = strip_leading_underscores
130
+ @record_aliases = {}
131
+ @record_aliases_by_tag_name = {}
132
+ @enum_aliases = {}
133
+ @record_visible_names = {}
134
+ @enum_visible_names = {}
135
+ @referenceable_record_declarations = {}
136
+ @referenceable_record_declarations_by_id = {}
137
+ @aggregate_declarations = {}
138
+ @synthetic_declarations = []
139
+ @manual_nullable_param_overrides = []
140
+ @manual_nullable_return_overrides = []
141
+ end
142
+
143
+ def generate
144
+ ast = dump_ast
145
+ index_referenceable_record_declarations(ast)
146
+ top_level_nodes = extract_top_level_header_nodes(ast)
147
+ @visible_typedef_names = top_level_nodes.filter_map do |node|
148
+ node["name"] if node["kind"] == "TypedefDecl" && allowed_declaration_name?(node["name"])
149
+ end
150
+ build_alias_maps(top_level_nodes)
151
+
152
+ declarations = []
153
+ declarations.concat(select_record_declarations(top_level_nodes))
154
+ validate_field_type_overrides!(declarations)
155
+ discover_synthetic_aggregate_dependencies(declarations)
156
+ discover_synthetic_field_type_dependencies(declarations)
157
+ declarations.concat(select_enum_declarations(top_level_nodes))
158
+ declarations.concat(select_type_alias_declarations(top_level_nodes))
159
+ declarations.concat(select_constant_declarations(top_level_nodes))
160
+ function_declarations = select_function_declarations(top_level_nodes)
161
+ validate_function_param_type_overrides!(function_declarations)
162
+ validate_function_return_type_overrides!(function_declarations)
163
+ declarations.concat(function_declarations)
164
+ declarations.sort_by! { |declaration| declaration[:index] }
165
+
166
+ emit_module(declarations)
167
+ end
168
+
169
+ def generate_with_report
170
+ source = generate
171
+ {
172
+ source:,
173
+ nullable_policy_report: nullable_policy_report,
174
+ }
175
+ end
176
+
177
+ private
178
+
179
+ def nullable_policy_report
180
+ parameter_entries = @manual_nullable_param_overrides.sort_by { |entry| [entry[:function], entry[:parameter]] }
181
+ return_entries = @manual_nullable_return_overrides.sort_by { |entry| entry[:function] }
182
+
183
+ {
184
+ module_name: @module_name,
185
+ header_path: @header_path,
186
+ summary: {
187
+ parameters: parameter_entries.length,
188
+ return_types: return_entries.length,
189
+ total: parameter_entries.length + return_entries.length,
190
+ },
191
+ manual_nullable_policy: {
192
+ parameters: parameter_entries,
193
+ return_types: return_entries,
194
+ },
195
+ }
196
+ end
197
+
198
+ include GeneratorAstParser
199
+ include GeneratorDeclaration
200
+ include GeneratorTypeMapper
201
+ include GeneratorEmitter
202
+ include GeneratorOverrides
203
+ end
204
+ end
205
+
206
+ class BindgenError < StandardError; end
207
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ class BindgenCLI
5
+ def self.start(argv = ARGV, out:, err:, help_printer:)
6
+ new(argv, out:, err:, help_printer:).start
7
+ end
8
+
9
+ def initialize(argv, out:, err:, help_printer:)
10
+ @argv = argv.dup
11
+ @out = out
12
+ @err = err
13
+ @help_printer = help_printer
14
+ end
15
+
16
+ def start
17
+ module_name = @argv.shift
18
+ header_path = @argv.shift
19
+ unless module_name && header_path
20
+ @err.puts("missing module name or header path")
21
+ print_help
22
+ return 1
23
+ end
24
+
25
+ require_relative "../bindings"
26
+
27
+ options = parse_options
28
+ return 1 unless options
29
+
30
+ output_path = options.delete(:output_path)
31
+ nullable_report_path = options.delete(:nullable_report_path)
32
+ if nullable_report_path
33
+ require "json"
34
+ result = Bindgen.generate_with_report(module_name:, header_path:, **options)
35
+ source = result.fetch(:source)
36
+ report_path = File.expand_path(nullable_report_path)
37
+ FileUtils.mkdir_p(File.dirname(report_path))
38
+ File.write(report_path, JSON.pretty_generate(result.fetch(:nullable_policy_report)))
39
+ else
40
+ source = Bindgen.generate(module_name:, header_path:, **options)
41
+ end
42
+
43
+ if output_path
44
+ FileUtils.mkdir_p(File.dirname(File.expand_path(output_path)))
45
+ File.write(output_path, source)
46
+ @out.puts("generated #{header_path} -> #{output_path}")
47
+ @out.puts("nullable report #{header_path} -> #{report_path}") if nullable_report_path
48
+ else
49
+ @out.write(source)
50
+ @err.puts("wrote nullable report #{report_path}") if nullable_report_path
51
+ end
52
+ 0
53
+ end
54
+
55
+ private
56
+
57
+ def print_help
58
+ @help_printer.call(@err)
59
+ end
60
+
61
+ def parse_options
62
+ options = {
63
+ output_path: nil,
64
+ nullable_report_path: nil,
65
+ link_libraries: [],
66
+ include_directives: [],
67
+ clang: ENV.fetch("CLANG", "clang"),
68
+ clang_args: [],
69
+ }
70
+
71
+ until @argv.empty?
72
+ option = @argv.shift
73
+ case option
74
+ when "-o", "--output"
75
+ value = @argv.shift
76
+ return missing_option_value(option) unless value
77
+
78
+ options[:output_path] = value
79
+ when "--link"
80
+ value = @argv.shift
81
+ return missing_option_value(option) unless value
82
+
83
+ options[:link_libraries] << value
84
+ when "--include"
85
+ value = @argv.shift
86
+ return missing_option_value(option) unless value
87
+
88
+ options[:include_directives] << value
89
+ when "--clang"
90
+ value = @argv.shift
91
+ return missing_option_value(option) unless value
92
+
93
+ options[:clang] = value
94
+ when "--clang-arg"
95
+ value = @argv.shift
96
+ return missing_option_value(option) unless value
97
+
98
+ options[:clang_args] << value
99
+ when "--nullable-report"
100
+ value = @argv.shift
101
+ return missing_option_value(option) unless value
102
+
103
+ options[:nullable_report_path] = value
104
+ else
105
+ @err.puts("unknown bindgen option #{option}")
106
+ print_help
107
+ return nil
108
+ end
109
+ end
110
+
111
+ options[:include_directives] = nil if options[:include_directives].empty?
112
+ options
113
+ end
114
+
115
+ def missing_option_value(option)
116
+ @err.puts("missing value for #{option}")
117
+ print_help
118
+ nil
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,210 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ module ImportedBindings
5
+ def self.default_bindings(root: MilkTea.root)
6
+ [
7
+ Binding.new(
8
+ name: "raymath",
9
+ module_name: "std.raymath",
10
+ binding_path: root.join("std/raymath.mt"),
11
+ raw_module_name: "std.c.raymath",
12
+ policy_path: root.join("bindings/imported/raymath.binding.json"),
13
+ ),
14
+ Binding.new(
15
+ name: "raylib",
16
+ module_name: "std.raylib",
17
+ binding_path: root.join("std/raylib.mt"),
18
+ raw_module_name: "std.c.raylib",
19
+ policy_path: root.join("bindings/imported/raylib.binding.json"),
20
+ ),
21
+ Binding.new(
22
+ name: "rlgl",
23
+ module_name: "std.rlgl",
24
+ binding_path: root.join("std/rlgl.mt"),
25
+ raw_module_name: "std.c.rlgl",
26
+ policy_path: root.join("bindings/imported/rlgl.binding.json"),
27
+ ),
28
+ Binding.new(
29
+ name: "raygui",
30
+ module_name: "std.raygui",
31
+ binding_path: root.join("std/raygui.mt"),
32
+ raw_module_name: "std.c.raygui",
33
+ policy_path: root.join("bindings/imported/raygui.binding.json"),
34
+ ),
35
+ Binding.new(
36
+ name: "sdl3",
37
+ module_name: "std.sdl3",
38
+ binding_path: root.join("std/sdl3.mt"),
39
+ raw_module_name: "std.c.sdl3",
40
+ policy_path: root.join("bindings/imported/sdl3.binding.json"),
41
+ ),
42
+ Binding.new(
43
+ name: "gl",
44
+ module_name: "std.gl",
45
+ binding_path: root.join("std/gl.mt"),
46
+ raw_module_name: "std.c.gl",
47
+ policy_path: root.join("bindings/imported/gl.binding.json"),
48
+ ),
49
+ Binding.new(
50
+ name: "glfw",
51
+ module_name: "std.glfw",
52
+ binding_path: root.join("std/glfw.mt"),
53
+ raw_module_name: "std.c.glfw",
54
+ policy_path: root.join("bindings/imported/glfw.binding.json"),
55
+ ),
56
+ Binding.new(
57
+ name: "box2d",
58
+ module_name: "std.box2d",
59
+ binding_path: root.join("std/box2d.mt"),
60
+ raw_module_name: "std.c.box2d",
61
+ policy_path: root.join("bindings/imported/box2d.binding.json"),
62
+ ),
63
+ Binding.new(
64
+ name: "cjson",
65
+ module_name: "std.cjson",
66
+ binding_path: root.join("std/cjson.mt"),
67
+ raw_module_name: "std.c.cjson",
68
+ policy_path: root.join("bindings/imported/cjson.binding.json"),
69
+ ),
70
+ Binding.new(
71
+ name: "flecs",
72
+ module_name: "std.flecs",
73
+ binding_path: root.join("std/flecs.mt"),
74
+ raw_module_name: "std.c.flecs",
75
+ policy_path: root.join("bindings/imported/flecs.binding.json"),
76
+ ),
77
+ Binding.new(
78
+ name: "libuv",
79
+ module_name: "std.libuv",
80
+ binding_path: root.join("std/libuv.mt"),
81
+ raw_module_name: "std.c.libuv",
82
+ policy_path: root.join("bindings/imported/libuv.binding.json"),
83
+ ),
84
+ Binding.new(
85
+ name: "enet",
86
+ module_name: "std.enet",
87
+ binding_path: root.join("std/enet.mt"),
88
+ raw_module_name: "std.c.enet",
89
+ policy_path: root.join("bindings/imported/enet.binding.json"),
90
+ ),
91
+ Binding.new(
92
+ name: "zstd",
93
+ module_name: "std.zstd",
94
+ binding_path: root.join("std/zstd.mt"),
95
+ raw_module_name: "std.c.zstd",
96
+ policy_path: root.join("bindings/imported/zstd.binding.json"),
97
+ ),
98
+ Binding.new(
99
+ name: "sqlite3",
100
+ module_name: "std.sqlite3",
101
+ binding_path: root.join("std/sqlite3.mt"),
102
+ raw_module_name: "std.c.sqlite3",
103
+ policy_path: root.join("bindings/imported/sqlite3.binding.json"),
104
+ ),
105
+ Binding.new(
106
+ name: "curl",
107
+ module_name: "std.curl",
108
+ binding_path: root.join("std/curl.mt"),
109
+ raw_module_name: "std.c.curl",
110
+ policy_path: root.join("bindings/imported/curl.binding.json"),
111
+ ),
112
+ Binding.new(
113
+ name: "pcre2",
114
+ module_name: "std.pcre2",
115
+ binding_path: root.join("std/pcre2.mt"),
116
+ raw_module_name: "std.c.pcre2",
117
+ policy_path: root.join("bindings/imported/pcre2.binding.json"),
118
+ ),
119
+ Binding.new(
120
+ name: "steamworks",
121
+ module_name: "std.steamworks",
122
+ binding_path: root.join("std/steamworks.mt"),
123
+ raw_module_name: "std.c.steamworks",
124
+ policy_path: root.join("bindings/imported/steamworks.binding.json"),
125
+ ),
126
+ Binding.new(
127
+ name: "miniaudio",
128
+ module_name: "std.miniaudio",
129
+ binding_path: root.join("std/miniaudio.mt"),
130
+ raw_module_name: "std.c.miniaudio",
131
+ policy_path: root.join("bindings/imported/miniaudio.binding.json"),
132
+ ),
133
+ Binding.new(
134
+ name: "tracy",
135
+ module_name: "std.tracy",
136
+ binding_path: root.join("std/tracy.mt"),
137
+ raw_module_name: "std.c.tracy",
138
+ policy_path: root.join("bindings/imported/tracy.binding.json"),
139
+ ),
140
+ Binding.new(
141
+ name: "rres",
142
+ module_name: "std.rres",
143
+ binding_path: root.join("std/rres.mt"),
144
+ raw_module_name: "std.c.rres",
145
+ policy_path: root.join("bindings/imported/rres.binding.json"),
146
+ ),
147
+ Binding.new(
148
+ name: "rpng",
149
+ module_name: "std.rpng",
150
+ binding_path: root.join("std/rpng.mt"),
151
+ raw_module_name: "std.c.rpng",
152
+ policy_path: root.join("bindings/imported/rpng.binding.json"),
153
+ ),
154
+ Binding.new(
155
+ name: "stb_image",
156
+ module_name: "std.stb_image",
157
+ binding_path: root.join("std/stb_image.mt"),
158
+ raw_module_name: "std.c.stb_image",
159
+ policy_path: root.join("bindings/imported/stb_image.binding.json"),
160
+ ),
161
+ Binding.new(
162
+ name: "stb_truetype",
163
+ module_name: "std.stb_truetype",
164
+ binding_path: root.join("std/stb_truetype.mt"),
165
+ raw_module_name: "std.c.stb_truetype",
166
+ policy_path: root.join("bindings/imported/stb_truetype.binding.json"),
167
+ ),
168
+ Binding.new(
169
+ name: "stb_image_write",
170
+ module_name: "std.stb_image_write",
171
+ binding_path: root.join("std/stb_image_write.mt"),
172
+ raw_module_name: "std.c.stb_image_write",
173
+ policy_path: root.join("bindings/imported/stb_image_write.binding.json"),
174
+ ),
175
+ Binding.new(
176
+ name: "stb_image_resize2",
177
+ module_name: "std.stb_image_resize2",
178
+ binding_path: root.join("std/stb_image_resize2.mt"),
179
+ raw_module_name: "std.c.stb_image_resize2",
180
+ policy_path: root.join("bindings/imported/stb_image_resize2.binding.json"),
181
+ ),
182
+ Binding.new(
183
+ name: "stb_rect_pack",
184
+ module_name: "std.stb_rect_pack",
185
+ binding_path: root.join("std/stb_rect_pack.mt"),
186
+ raw_module_name: "std.c.stb_rect_pack",
187
+ policy_path: root.join("bindings/imported/stb_rect_pack.binding.json"),
188
+ ),
189
+ Binding.new(
190
+ name: "stb_vorbis",
191
+ module_name: "std.stb_vorbis",
192
+ binding_path: root.join("std/stb_vorbis.mt"),
193
+ raw_module_name: "std.c.stb_vorbis",
194
+ policy_path: root.join("bindings/imported/stb_vorbis.binding.json"),
195
+ ),
196
+ Binding.new(
197
+ name: "cgltf",
198
+ module_name: "std.cgltf",
199
+ binding_path: root.join("std/cgltf.mt"),
200
+ raw_module_name: "std.c.cgltf",
201
+ policy_path: root.join("bindings/imported/cgltf.binding.json"),
202
+ ),
203
+ ]
204
+ end
205
+
206
+ def self.default_registry(root: MilkTea.root)
207
+ Registry.new(default_bindings(root:))
208
+ end
209
+ end
210
+ end