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,319 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ module Bindgen
5
+ class Generator
6
+ module GeneratorDeclaration
7
+ private
8
+
9
+ def select_record_declarations(nodes)
10
+ selected = {}
11
+ type_aliases = []
12
+
13
+ nodes.each_with_index do |node, index|
14
+ record_node, original_name = case node["kind"]
15
+ when "RecordDecl"
16
+ [node, @record_aliases[node["id"]] || node["name"]]
17
+ when "TypedefDecl"
18
+ target = typedef_target(node)
19
+ next unless target&.fetch(:kind, nil) == "RecordDecl"
20
+
21
+ record_node = @referenceable_record_declarations_by_id[target[:id]] || @referenceable_record_declarations[target[:name]]
22
+ next unless record_node
23
+
24
+ primary_alias = @record_aliases[target[:id]]
25
+ if primary_alias && primary_alias != node["name"] && allowed_declaration_name?(node["name"])
26
+ type_alias_name = visible_type_name(node["name"])
27
+ type_alias_target = visible_type_name(primary_alias)
28
+ unless type_aliases.any? { |ta| ta[:name] == type_alias_name }
29
+ type_aliases << { index:, kind: "type_alias", name: type_alias_name, mapped_type: type_alias_target }
30
+ end
31
+ next
32
+ end
33
+
34
+ [record_node, node["name"]]
35
+ else
36
+ next
37
+ end
38
+
39
+ next unless %w[struct union].include?(record_node["tagUsed"])
40
+
41
+ next unless original_name
42
+ next unless allowed_declaration_name?(original_name)
43
+
44
+ visible_name = visible_type_name(original_name)
45
+
46
+ candidate = {
47
+ index:,
48
+ kind: record_complete_definition?(record_node) ? record_node["tagUsed"] : "opaque",
49
+ name: visible_name,
50
+ linkage_name: record_c_name(record_node),
51
+ node: record_node,
52
+ }
53
+
54
+ existing = selected[visible_name]
55
+ if existing.nil? || (existing[:kind] == "opaque" && candidate[:kind] != "opaque")
56
+ selected[visible_name] = candidate
57
+ end
58
+ end
59
+
60
+ declarations = selected.values + type_aliases
61
+
62
+ @record_visible_names = {}
63
+ selected.each_value do |declaration|
64
+ tag_name = declaration[:node]["name"]
65
+ @record_visible_names[tag_name] = declaration[:name] if tag_name
66
+ @record_visible_names[declaration[:name]] = declaration[:name]
67
+ @aggregate_declarations[declaration[:name]] = declaration[:node] if %w[struct union].include?(declaration[:kind])
68
+ end
69
+ declarations
70
+ end
71
+
72
+ def record_complete_definition?(node)
73
+ return true if node["completeDefinition"]
74
+
75
+ Array(node["inner"]).any? { |child| child["kind"] == "FieldDecl" }
76
+ end
77
+
78
+ def select_enum_declarations(nodes)
79
+ selected = {}
80
+
81
+ nodes.each_with_index do |node, index|
82
+ next unless node["kind"] == "EnumDecl"
83
+
84
+ original_name = @enum_aliases[node["id"]] || node["name"]
85
+ next unless original_name
86
+ next unless allowed_declaration_name?(original_name)
87
+
88
+ visible_name = visible_type_name(original_name)
89
+
90
+ selected[visible_name] = { index:, kind: enum_kind(node), name: visible_name, node: }
91
+ end
92
+
93
+ @enum_visible_names = {}
94
+ selected.each_value do |declaration|
95
+ tag_name = declaration[:node]["name"]
96
+ @enum_visible_names[tag_name] = declaration[:name] if tag_name
97
+ @enum_visible_names[declaration[:name]] = declaration[:name]
98
+ end
99
+ selected.values
100
+ end
101
+
102
+ def select_type_alias_declarations(nodes)
103
+ alias_names = nodes.filter_map { |node| node["name"] if node["kind"] == "TypedefDecl" }
104
+
105
+ nodes.each_with_index.filter_map do |node, index|
106
+ next unless node["kind"] == "TypedefDecl"
107
+ next if typedef_target(node)
108
+ next unless allowed_declaration_name?(node["name"])
109
+
110
+ qual_type = alias_qual_type(node)
111
+ mapped_type = if extract_function_proto(node)
112
+ map_function_pointer_typedef(node, context: node["name"])
113
+ else
114
+ map_c_type(qual_type, context: node["name"])
115
+ end
116
+ next if node["name"] == mapped_type
117
+ next if unresolved_alias_target?(mapped_type, alias_names)
118
+
119
+ {
120
+ index:,
121
+ kind: "type_alias",
122
+ name: visible_type_name(node["name"]),
123
+ mapped_type:,
124
+ }
125
+ rescue BindgenError
126
+ nil
127
+ end
128
+
129
+ end
130
+
131
+ def alias_qual_type(node)
132
+ type_qual_type(node)
133
+ end
134
+
135
+ def select_function_declarations(nodes)
136
+ selected = {}
137
+
138
+ nodes.each_with_index do |node, index|
139
+ next unless node["kind"] == "FunctionDecl"
140
+ has_body = Array(node["inner"]).any? { |child| child["kind"] == "CompoundStmt" }
141
+ next if node["storageClass"] == "static" && !@allow_static_inline_functions
142
+ next if has_body && !(node["storageClass"] == "static" && @allow_static_inline_functions)
143
+ next unless allowed_declaration_name?(node["name"])
144
+
145
+ params = Array(node["inner"]).select { |child| child["kind"] == "ParmVarDecl" }.each_with_index.map do |param, param_index|
146
+ param_name = param["name"] || "arg#{param_index}"
147
+ override_type = function_param_type_override(node["name"], param_name)
148
+ record_nullable_param_override(node["name"], param_name, param, override_type) if override_type
149
+ {
150
+ name: param_name,
151
+ type: override_type || map_type_node(param, context: "parameter #{param_name} of #{node["name"]}"),
152
+ }
153
+ end
154
+
155
+ override_return_type = function_return_type_override(node["name"])
156
+ record_nullable_return_override(node, override_return_type) if override_return_type
157
+ return_type = override_return_type || map_c_type(function_return_type(node), context: "return type of #{node["name"]}")
158
+ declaration = {
159
+ index:,
160
+ kind: "function",
161
+ name: node["name"],
162
+ params:,
163
+ variadic: node["variadic"],
164
+ return_type:,
165
+ }
166
+ selected[declaration[:name]] ||= declaration
167
+ rescue BindgenError
168
+ next
169
+ end
170
+
171
+ selected.values
172
+ end
173
+
174
+ def validate_function_param_type_overrides!(function_declarations)
175
+ return if @function_param_type_overrides.empty?
176
+
177
+ declarations_by_name = function_declarations.to_h { |declaration| [declaration[:name], declaration] }
178
+
179
+ @function_param_type_overrides.each do |function_name, param_overrides|
180
+ declaration = declarations_by_name[function_name]
181
+ raise BindgenError, "function_param_type_overrides references unknown function #{function_name} for #{@header_path}" unless declaration
182
+
183
+ param_names = declaration[:params].map { |param| param[:name] }
184
+ param_overrides.each_key do |param_name|
185
+ next if param_names.include?(param_name)
186
+
187
+ raise BindgenError, "function_param_type_overrides references unknown parameter #{function_name}.#{param_name} for #{@header_path}"
188
+ end
189
+ end
190
+ end
191
+
192
+ def validate_function_return_type_overrides!(function_declarations)
193
+ return if @function_return_type_overrides.empty?
194
+
195
+ declarations_by_name = function_declarations.to_h { |declaration| [declaration[:name], declaration] }
196
+
197
+ @function_return_type_overrides.each_key do |function_name|
198
+ next if declarations_by_name.key?(function_name)
199
+
200
+ raise BindgenError, "function_return_type_overrides references unknown function #{function_name} for #{@header_path}"
201
+ end
202
+ end
203
+
204
+ def validate_field_type_overrides!(record_declarations)
205
+ return if @field_type_overrides.empty?
206
+
207
+ declarations_by_name = record_declarations.to_h { |declaration| [declaration[:name], declaration] }
208
+
209
+ @field_type_overrides.each do |type_name, field_overrides|
210
+ declaration = declarations_by_name[type_name]
211
+ raise BindgenError, "field_type_overrides references unknown type #{type_name} for #{@header_path}" unless declaration
212
+
213
+ field_names = Array(declaration[:node]["inner"]).select { |child| child["kind"] == "FieldDecl" }.map { |field| field["name"] }
214
+ field_overrides.each_key do |field_name|
215
+ next if field_names.include?(field_name)
216
+
217
+ raise BindgenError, "field_type_overrides references unknown field #{type_name}.#{field_name} for #{@header_path}"
218
+ end
219
+ end
220
+ end
221
+
222
+ def select_constant_declarations(nodes)
223
+ nodes.each_with_index.filter_map do |node, index|
224
+ next unless node["kind"] == "VarDecl"
225
+ next if node["isInvalid"]
226
+ next unless constant_var_decl?(node)
227
+ next unless allowed_declaration_name?(constant_name_for(node))
228
+
229
+ begin
230
+ initializer = Array(node["inner"]).first
231
+ type = macro_string_constant_type(node, initializer, context: constant_name_for(node))
232
+ type ||= map_c_type(constant_qual_type(node), context: constant_name_for(node))
233
+ value = lower_constant_expression(initializer, expected_type: type, context: constant_name_for(node))
234
+ rescue BindgenError
235
+ raise unless macro_probe_declaration?(node)
236
+
237
+ next
238
+ end
239
+
240
+ {
241
+ index:,
242
+ kind: "const",
243
+ name: constant_name_for(node),
244
+ type:,
245
+ value:,
246
+ }
247
+ end
248
+ end
249
+
250
+ def macro_string_constant_type(node, initializer, context:)
251
+ return nil unless macro_probe_declaration?(node)
252
+ return nil unless constant_expression_kind(initializer) == "StringLiteral"
253
+
254
+ qual_type = normalize_c_type(constant_qual_type(node))
255
+ qual_type, = extract_top_level_nullability(qual_type)
256
+ return "cstr" if string_literal_macro_compatible_c_type?(qual_type)
257
+
258
+ raise BindgenError, "unsupported string macro type #{qual_type.inspect} for #{context}"
259
+ end
260
+
261
+ def constant_expression_kind(node)
262
+ current = node
263
+
264
+ while current.is_a?(Hash)
265
+ case current["kind"]
266
+ when "ImplicitCastExpr", "ConstantExpr", "CompoundLiteralExpr", "ParenExpr"
267
+ current = Array(current["inner"]).first
268
+ else
269
+ return current["kind"]
270
+ end
271
+ end
272
+
273
+ nil
274
+ end
275
+
276
+ def constant_var_decl?(node)
277
+ qual_type = node.dig("type", "qualType")
278
+ node["init"] && strip_qualifiers(normalize_c_type(qual_type)) != normalize_c_type(qual_type)
279
+ end
280
+
281
+ def constant_qual_type(node)
282
+ qual_type = node.dig("type", "qualType")
283
+ if macro_probe_declaration?(node) && qual_type.to_s.include?("typeof")
284
+ node.dig("type", "desugaredQualType") || qual_type
285
+ else
286
+ qual_type
287
+ end
288
+ end
289
+
290
+ def function_return_type(node)
291
+ qual_type = type_qual_type(node)
292
+ match = qual_type&.match(/\A(.+?)\s*\((?:.*)\)\z/)
293
+ raise BindgenError, "unsupported function type for #{node["name"]}: #{qual_type.inspect}" unless match
294
+
295
+ match[1]
296
+ end
297
+
298
+ def type_qual_type(node)
299
+ qual_type = node.dig("type", "qualType")
300
+ return qual_type if qual_type.to_s.match?(/_Nullable|_Nonnull|_Null_unspecified|_Nullable_result/)
301
+
302
+ node.dig("type", "desugaredQualType") || qual_type
303
+ end
304
+
305
+ def enum_kind(node)
306
+ values = enum_member_values(node).map { |member| member[:value] }
307
+ non_zero = values.reject(&:zero?)
308
+ return "enum" if non_zero.empty?
309
+
310
+ non_zero.all? { |value| power_of_two?(value) } ? "flags" : "enum"
311
+ end
312
+
313
+ def power_of_two?(value)
314
+ value.positive? && (value & (value - 1)).zero?
315
+ end
316
+ end
317
+ end
318
+ end
319
+ end