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,609 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ module TypePredicates
5
+ def method_dispatch_receiver_type(receiver_type)
6
+ return receiver_type.definition if receiver_type.is_a?(Types::StructInstance) || receiver_type.is_a?(Types::VariantInstance)
7
+ if receiver_type.is_a?(Types::Nullable)
8
+ dispatch_base_type = method_dispatch_receiver_type(receiver_type.base)
9
+ return receiver_type if dispatch_base_type == receiver_type.base
10
+
11
+ return Types::Registry.nullable(dispatch_base_type)
12
+ end
13
+ return receiver_type unless receiver_type.is_a?(Types::GenericInstance)
14
+
15
+ dispatch_receiver_type = Types::Registry.generic_instance(
16
+ receiver_type.name,
17
+ receiver_type.arguments.each_with_index.map do |argument, index|
18
+ argument.is_a?(Types::LiteralTypeArg) ? argument : Types::TypeVar.new("__receiver_arg#{index}")
19
+ end,
20
+ )
21
+ dispatch_receiver_type == receiver_type ? receiver_type : dispatch_receiver_type
22
+ end
23
+
24
+ def task_root_proc_type?(type)
25
+ proc_type?(type) && type.params.empty? && type.return_type.is_a?(Types::Task)
26
+ end
27
+
28
+ def function_type_matches_proc_type?(function_type, proc_type)
29
+ return false if function_type.receiver_type || function_type.variadic
30
+ return false unless function_type.params.length == proc_type.params.length
31
+ return false unless function_type.return_type == proc_type.return_type
32
+
33
+ function_type.params.zip(proc_type.params).all? do |function_param, proc_param|
34
+ next false unless function_param.mutable == proc_param.mutable
35
+
36
+ function_param.type == proc_param.type ||
37
+ same_external_opaque_handle_pointer_compatibility?(function_param.type, proc_param.type)
38
+ end
39
+ end
40
+
41
+ def null_assignable_to?(actual_type, expected_type)
42
+ return false unless actual_type.is_a?(Types::Null)
43
+ return false unless expected_type.is_a?(Types::Nullable)
44
+ return true unless actual_type.target_type
45
+
46
+ actual_type.target_type == expected_type.base
47
+ end
48
+
49
+ def external_typed_null_pointer_compatibility?(actual_type, expected_type)
50
+ return false unless actual_type.is_a?(Types::Null)
51
+ return false unless actual_type.target_type
52
+ return false if expected_type.is_a?(Types::Nullable)
53
+ return true if expected_type == Types::Registry.primitive("cstr") && char_pointer_type?(actual_type.target_type)
54
+ return false unless pointer_type?(expected_type)
55
+
56
+ actual_type.target_type == expected_type
57
+ end
58
+
59
+ def numeric_constant_fits_type?(value, expected_type)
60
+ if expected_type.integer?
61
+ integer_constant_fits_type?(value, expected_type)
62
+ else
63
+ float_constant_fits_type?(value, expected_type)
64
+ end
65
+ end
66
+
67
+ def integer_constant_fits_type?(value, expected_type)
68
+ integer_value = exact_integer_constant_value(value)
69
+ return false if integer_value.nil?
70
+
71
+ value_fits_integer_type?(integer_value, expected_type)
72
+ end
73
+
74
+ def float_constant_fits_type?(value, expected_type)
75
+ return false unless value.is_a?(Numeric)
76
+ return false unless value.finite?
77
+
78
+ if expected_type.name == "float"
79
+ return value.abs <= (1 << 24) if value.is_a?(Integer)
80
+
81
+ exactly_representable_float32?(value.to_f)
82
+ else
83
+ return true if expected_type.name == "double"
84
+
85
+ false
86
+ end
87
+ end
88
+
89
+ def exact_integer_constant_value(value)
90
+ return value if value.is_a?(Integer)
91
+ return nil unless value.is_a?(Float) && value.finite?
92
+
93
+ integer_value = value.to_i
94
+ integer_value.to_f == value ? integer_value : nil
95
+ end
96
+
97
+ def value_fits_integer_type?(value, expected_type)
98
+ return false unless expected_type.is_a?(Types::Primitive) && expected_type.integer?
99
+
100
+ width = expected_type.integer_width
101
+ return false if width.nil?
102
+
103
+ min_value, max_value = if expected_type.signed_integer?
104
+ [-(1 << (width - 1)), (1 << (width - 1)) - 1]
105
+ else
106
+ [0, (1 << width) - 1]
107
+ end
108
+
109
+ value >= min_value && value <= max_value
110
+ end
111
+
112
+ def exactly_representable_float32?(value)
113
+ [value].pack("f").unpack1("f") == value
114
+ end
115
+
116
+ def integer_to_char_compatibility?(actual_type, expected_type)
117
+ char_type?(expected_type) && integer_like_char_source_type?(actual_type)
118
+ end
119
+
120
+ def integer_like_char_source_type?(type)
121
+ return true if type.is_a?(Types::Primitive) && type.integer?
122
+ return true if type.is_a?(Types::EnumBase) && type.backing_type.is_a?(Types::Primitive) && type.backing_type.integer?
123
+
124
+ false
125
+ end
126
+
127
+ def char_type?(type)
128
+ type.is_a?(Types::Primitive) && type.name == "char"
129
+ end
130
+
131
+ def external_numeric_compatibility?(actual_type, expected_type)
132
+ return false unless actual_type.is_a?(Types::Primitive) && expected_type.is_a?(Types::Primitive)
133
+ return false unless actual_type.numeric? && expected_type.numeric?
134
+
135
+ return lossless_external_integer_compatibility?(actual_type, expected_type) if actual_type.integer? && expected_type.integer?
136
+ return expected_type.float_width >= actual_type.float_width if actual_type.float? && expected_type.float?
137
+
138
+ false
139
+ end
140
+
141
+ def lossless_external_integer_compatibility?(actual_type, expected_type)
142
+ return false unless actual_type.fixed_width_integer? && expected_type.fixed_width_integer?
143
+
144
+ if actual_type.signed_integer? == expected_type.signed_integer?
145
+ return expected_type.integer_width >= actual_type.integer_width
146
+ end
147
+
148
+ return false if actual_type.signed_integer?
149
+
150
+ expected_type.signed_integer? && expected_type.integer_width > actual_type.integer_width
151
+ end
152
+
153
+ def lossless_integer_compatibility?(actual_type, expected_type)
154
+ return false unless actual_type.is_a?(Types::Primitive) && expected_type.is_a?(Types::Primitive)
155
+ return false unless actual_type.integer? && expected_type.integer?
156
+
157
+ lossless_external_integer_compatibility?(actual_type, expected_type)
158
+ end
159
+
160
+ def contextual_int_to_float_compatibility?(actual_type, expected_type)
161
+ actual_type.is_a?(Types::Primitive) && actual_type.integer? &&
162
+ expected_type.is_a?(Types::Primitive) && expected_type.float?
163
+ end
164
+
165
+ def contextual_int_to_float_target?(type)
166
+ type.is_a?(Types::Primitive) && type.float?
167
+ end
168
+
169
+ def mutable_to_const_pointer_compatibility?(actual_type, expected_type)
170
+ return mutable_to_const_pointer_compatibility?(actual_type.base, expected_type.base) if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
171
+ return mutable_to_const_pointer_compatibility?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
172
+ return false if actual_type.is_a?(Types::Nullable)
173
+ return false unless (mutable_pointer_type?(actual_type) || own_type?(actual_type)) && const_pointer_type?(expected_type)
174
+
175
+ pointee_type(actual_type) == pointee_type(expected_type)
176
+ end
177
+
178
+ def own_to_raw_pointer_compatibility?(actual_type, expected_type)
179
+ return own_to_raw_pointer_compatibility?(actual_type.base, expected_type.base) if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
180
+ return own_to_raw_pointer_compatibility?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
181
+ return false if actual_type.is_a?(Types::Nullable)
182
+ return false unless own_type?(actual_type)
183
+ return false unless mutable_pointer_type?(expected_type) || const_pointer_type?(expected_type)
184
+
185
+ pointee_type(actual_type) == pointee_type(expected_type)
186
+ end
187
+
188
+ def foreign_span_boundary_compatible?(public_type, boundary_type)
189
+ return false unless public_type.is_a?(Types::Span) && boundary_type.is_a?(Types::Span)
190
+
191
+ foreign_boundary_element_compatible?(public_type.element_type, boundary_type.element_type)
192
+ end
193
+
194
+ def foreign_char_pointer_buffer_boundary_compatible?(public_type, boundary_type)
195
+ return false unless char_pointer_type?(boundary_type)
196
+
197
+ return true if public_type.is_a?(Types::Span) && public_type.element_type == Types::Registry.primitive("char")
198
+ return true if char_array_text_type?(public_type)
199
+ return true if str_buffer_type?(public_type)
200
+
201
+ false
202
+ end
203
+
204
+ def foreign_boundary_element_compatible?(public_type, boundary_type)
205
+ return true if public_type == boundary_type
206
+ return true if public_type == Types::Registry.string_view && boundary_type == Types::Registry.primitive("cstr")
207
+ return true if public_type == Types::Registry.string_view && char_pointer_type?(boundary_type)
208
+
209
+ foreign_identity_projection_compatible?(public_type, boundary_type)
210
+ end
211
+
212
+ def foreign_identity_projection_compatible?(actual_type, expected_type)
213
+ foreign_identity_projection_cast_compatible?(actual_type, expected_type) ||
214
+ foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type)
215
+ end
216
+
217
+ def foreign_identity_projection_cast_compatible?(actual_type, expected_type)
218
+ return true if actual_type == expected_type
219
+ return true if mutable_to_const_pointer_compatibility?(actual_type, expected_type)
220
+ return true if same_external_opaque_c_name?(actual_type, expected_type)
221
+ return true if foreign_function_type_projection_compatible?(actual_type, expected_type)
222
+ return true if native_foreign_layout_compatible?(actual_type, expected_type)
223
+ return true if native_foreign_layout_compatible?(expected_type, actual_type)
224
+ return true if quat_vec4_layout_compatible?(actual_type, expected_type)
225
+
226
+ if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
227
+ return foreign_identity_projection_cast_compatible?(actual_type.base, expected_type.base)
228
+ end
229
+
230
+ return foreign_identity_projection_cast_compatible?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
231
+ return false if actual_type.is_a?(Types::Nullable)
232
+
233
+ return true if same_external_opaque_handle_pointer_compatibility?(actual_type, expected_type)
234
+
235
+ if pointer_type?(actual_type) && pointer_type?(expected_type)
236
+ return false if const_pointer_type?(actual_type) && mutable_pointer_type?(expected_type)
237
+ return true if void_pointer_type?(actual_type) || void_pointer_type?(expected_type)
238
+
239
+ return true if foreign_identity_projection_cast_compatible?(actual_type.arguments.first, expected_type.arguments.first)
240
+
241
+ return foreign_external_layout_compatible?(actual_type.arguments.first, expected_type.arguments.first)
242
+ end
243
+
244
+ return true if void_pointer_type?(actual_type) && opaque_type?(expected_type)
245
+ return true if opaque_type?(actual_type) && void_pointer_type?(expected_type)
246
+ return true if char_pointer_type?(actual_type) && expected_type == Types::Registry.primitive("cstr")
247
+ return true if actual_type == Types::Registry.primitive("cstr") && char_pointer_type?(expected_type)
248
+
249
+ false
250
+ end
251
+
252
+ def same_external_opaque_handle_pointer_compatibility?(actual_type, expected_type)
253
+ if actual_type.is_a?(Types::Opaque) && pointer_type?(expected_type)
254
+ return same_external_opaque_c_name?(actual_type, expected_type.arguments.first)
255
+ end
256
+
257
+ if pointer_type?(actual_type) && expected_type.is_a?(Types::Opaque)
258
+ return same_external_opaque_c_name?(actual_type.arguments.first, expected_type)
259
+ end
260
+
261
+ false
262
+ end
263
+
264
+ def foreign_function_type_projection_compatible?(actual_type, expected_type)
265
+ return false unless actual_type.is_a?(Types::Function) && expected_type.is_a?(Types::Function)
266
+ return false unless actual_type.receiver_type == expected_type.receiver_type
267
+ return false unless actual_type.variadic == expected_type.variadic
268
+ return false unless actual_type.params.length == expected_type.params.length
269
+ return false unless foreign_identity_projection_compatible?(actual_type.return_type, expected_type.return_type)
270
+
271
+ actual_type.params.zip(expected_type.params).all? do |actual_param, expected_param|
272
+ actual_param.mutable == expected_param.mutable &&
273
+ actual_param.passing_mode == expected_param.passing_mode &&
274
+ actual_param.boundary_type == expected_param.boundary_type &&
275
+ foreign_identity_projection_compatible?(actual_param.type, expected_param.type)
276
+ end
277
+ end
278
+
279
+ def same_external_opaque_c_name?(actual_type, expected_type)
280
+ return false unless actual_type.is_a?(Types::Opaque) && expected_type.is_a?(Types::Opaque)
281
+ return false unless actual_type.external || actual_type.linkage_name
282
+ return false unless expected_type.external || expected_type.linkage_name
283
+
284
+ foreign_opaque_c_name(actual_type) == foreign_opaque_c_name(expected_type)
285
+ end
286
+
287
+ def foreign_opaque_c_name(type)
288
+ type.linkage_name || type.name
289
+ end
290
+
291
+ def foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type)
292
+ if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
293
+ return foreign_identity_projection_reinterpret_compatible?(actual_type.base, expected_type.base)
294
+ end
295
+
296
+ return foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
297
+ return false if actual_type.is_a?(Types::Nullable)
298
+
299
+ foreign_external_layout_compatible?(actual_type, expected_type)
300
+ end
301
+
302
+ def foreign_external_layout_compatible?(actual_type, expected_type, seen = {})
303
+ return false unless actual_type.is_a?(Types::Struct) && expected_type.is_a?(Types::Struct)
304
+ return false if actual_type.is_a?(Types::Union) != expected_type.is_a?(Types::Union)
305
+ return false unless actual_type.external && expected_type.external
306
+ return false unless actual_type.name == expected_type.name
307
+ return false unless actual_type.packed == expected_type.packed
308
+ return false unless actual_type.alignment == expected_type.alignment
309
+
310
+ key = [actual_type.object_id, expected_type.object_id]
311
+ return true if seen[key]
312
+
313
+ seen[key] = true
314
+ actual_fields = actual_type.fields
315
+ expected_fields = expected_type.fields
316
+ return false unless actual_fields.keys == expected_fields.keys
317
+
318
+ actual_fields.all? do |field_name, field_type|
319
+ foreign_external_layout_field_compatible?(field_type, expected_fields.fetch(field_name), seen)
320
+ end
321
+ end
322
+
323
+ def foreign_external_layout_field_compatible?(actual_type, expected_type, seen)
324
+ return true if actual_type == expected_type
325
+
326
+ if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
327
+ return foreign_external_layout_field_compatible?(actual_type.base, expected_type.base, seen)
328
+ end
329
+
330
+ if pointer_type?(actual_type) && pointer_type?(expected_type)
331
+ return foreign_external_layout_field_compatible?(actual_type.arguments.first, expected_type.arguments.first, seen)
332
+ end
333
+
334
+ if array_type?(actual_type) && array_type?(expected_type)
335
+ return false unless array_length(actual_type) == array_length(expected_type)
336
+
337
+ return foreign_external_layout_field_compatible?(array_element_type(actual_type), array_element_type(expected_type), seen)
338
+ end
339
+
340
+ foreign_external_layout_compatible?(actual_type, expected_type, seen)
341
+ end
342
+
343
+ def void_pointer_type?(type)
344
+ pointer_type?(type) && type.arguments.first == Types::Registry.primitive("void")
345
+ end
346
+
347
+ def native_foreign_layout_compatible?(native_type, foreign_type)
348
+ return false unless (native_type.is_a?(Types::Vector) || native_type.is_a?(Types::Matrix) || native_type.is_a?(Types::Quaternion))
349
+ return false unless foreign_type.is_a?(Types::Struct) && foreign_type.external
350
+
351
+ native_flat = flatten_field_types(native_type)
352
+ foreign_flat = flatten_field_types(foreign_type)
353
+ return false unless native_flat.size == foreign_flat.size
354
+
355
+ native_flat.zip(foreign_flat).all? { |nf, ff| nf == ff }
356
+ end
357
+
358
+ def quat_vec4_layout_compatible?(a, b)
359
+ (a.is_a?(Types::Quaternion) && b.is_a?(Types::Vector) && b.width == 4 && b.element_type.name == "float") ||
360
+ (b.is_a?(Types::Quaternion) && a.is_a?(Types::Vector) && a.width == 4 && a.element_type.name == "float")
361
+ end
362
+
363
+ def flatten_field_types(type)
364
+ if type.is_a?(Types::Primitive)
365
+ [type]
366
+ elsif type.respond_to?(:fields) && type.fields
367
+ type.fields.values.flat_map { |ft| flatten_field_types(ft) }
368
+ else
369
+ [type]
370
+ end
371
+ end
372
+
373
+ def char_pointer_type?(type)
374
+ pointer_type?(type) && type.arguments.first == Types::Registry.primitive("char")
375
+ end
376
+
377
+ def opaque_type?(type)
378
+ type.is_a?(Types::Opaque)
379
+ end
380
+
381
+ def pointer_type?(type)
382
+ mutable_pointer_type?(type) || const_pointer_type?(type) || own_type?(type)
383
+ end
384
+
385
+ def mutable_pointer_type?(type)
386
+ type.is_a?(Types::GenericInstance) && type.name == "ptr" && type.arguments.length == 1
387
+ end
388
+
389
+ def const_pointer_type?(type)
390
+ type.is_a?(Types::GenericInstance) && type.name == "const_ptr" && type.arguments.length == 1
391
+ end
392
+
393
+ def own_type?(type)
394
+ type.is_a?(Types::GenericInstance) && type.name == "own" && type.arguments.length == 1
395
+ end
396
+
397
+ def owned_referent_type(type)
398
+ type.arguments.first if own_type?(type)
399
+ end
400
+
401
+ def ref_type?(type)
402
+ type.is_a?(Types::GenericInstance) && type.name == "ref" && [1, 2].include?(type.arguments.length)
403
+ end
404
+
405
+ def atomic_type?(type)
406
+ type.is_a?(Types::GenericInstance) && type.name == "atomic" && type.arguments.length == 1
407
+ end
408
+
409
+ def atomic_element_type(type)
410
+ type.arguments.first
411
+ end
412
+
413
+ def ref_type_without_lifetime?(type)
414
+ type.is_a?(Types::GenericInstance) && type.name == "ref" && type.arguments.length == 1
415
+ end
416
+
417
+ def ref_lifetime(type)
418
+ return unless type.is_a?(Types::GenericInstance) && type.name == "ref" && type.arguments.length == 2
419
+
420
+ type.arguments.first
421
+ end
422
+
423
+ def dyn_type?(type)
424
+ type.is_a?(Types::Dyn)
425
+ end
426
+
427
+ def task_type?(type)
428
+ type.is_a?(Types::Task)
429
+ end
430
+
431
+ def struct_with_target_type?(type)
432
+ type.is_a?(Types::Struct) || type.is_a?(Types::Vector) || type.is_a?(Types::Matrix) || type.is_a?(Types::Quaternion)
433
+ end
434
+
435
+ def proc_type?(type)
436
+ type.is_a?(Types::Proc)
437
+ end
438
+
439
+ def pointee_type(type)
440
+ return unless pointer_type?(type)
441
+
442
+ type.arguments.first
443
+ end
444
+
445
+ def referenced_type(type)
446
+ return unless ref_type?(type)
447
+
448
+ type.arguments.length == 1 ? type.arguments.first : type.arguments[1]
449
+ end
450
+
451
+ def const_pointer_to(type)
452
+ Types::Registry.generic_instance("const_ptr", [type])
453
+ end
454
+
455
+ def call_arity_matches?(function_type, actual_count)
456
+ return actual_count >= function_type.params.length if function_type.is_a?(Types::Function) && function_type.variadic
457
+
458
+ actual_count == function_type.params.length
459
+ end
460
+
461
+ def arity_error_message(function_type, name, actual_count)
462
+ if function_type.is_a?(Types::Function) && function_type.variadic
463
+ "function #{name} expects at least #{function_type.params.length} arguments, got #{actual_count}"
464
+ else
465
+ "function #{name} expects #{function_type.params.length} arguments, got #{actual_count}"
466
+ end
467
+ end
468
+
469
+ def string_builder_type?(type)
470
+ type.respond_to?(:name) && type.respond_to?(:module_name) && type.name == "String" && type.module_name == "std.string"
471
+ end
472
+
473
+ def string_builder_ref_type?(type)
474
+ ref_type?(type) && string_builder_type?(referenced_type(type))
475
+ end
476
+
477
+ def callable_param_ref_supported?(type)
478
+ case type
479
+ when Types::Proc
480
+ type.params.all? { |param| ref_type?(param.type) || !contains_ref_type?(param.type) } &&
481
+ !contains_ref_type?(type.return_type)
482
+ when Types::Function
483
+ type.params.all? { |param| ref_type?(param.type) || !contains_ref_type?(param.type) } &&
484
+ !contains_ref_type?(type.return_type) &&
485
+ (type.receiver_type.nil? || !contains_ref_type?(type.receiver_type))
486
+ else
487
+ false
488
+ end
489
+ end
490
+
491
+ def contains_ref_type?(type, visited = {}, allow_lifetimes: [])
492
+ visitor = ContainsRefTypeVisitor.new(allow_lifetimes:)
493
+ visitor.visit(type)
494
+ visitor.found?
495
+ end
496
+
497
+ def contains_type_var?(type)
498
+ visitor = ContainsTypeVarVisitor.new
499
+ visitor.visit(type)
500
+ visitor.found?
501
+ end
502
+
503
+ def collection_loop_type(type)
504
+ return type.arguments.first if Types.array_type?(type)
505
+ return type.element_type if type.is_a?(Types::Span)
506
+
507
+ nil
508
+ end
509
+
510
+ def collection_loop_binding_type(iterable_type, element_type)
511
+ return nil unless Types.array_type?(iterable_type) || iterable_type.is_a?(Types::Span)
512
+ return nil unless collection_loop_ref_element_type?(element_type)
513
+
514
+ Types::Registry.generic_instance("ref", [element_type])
515
+ end
516
+
517
+ def collection_loop_ref_element_type?(type)
518
+ type.is_a?(Types::Struct)
519
+ end
520
+
521
+ def integer_type_argument?(argument)
522
+ argument.is_a?(Types::LiteralTypeArg) && argument.value.is_a?(Integer)
523
+ end
524
+
525
+ def generic_integer_type_argument?(argument)
526
+ integer_type_argument?(argument) || argument.is_a?(Types::TypeVar)
527
+ end
528
+
529
+ def validate_generic_type!(name, arguments, &error)
530
+ case name
531
+ when "ptr"
532
+ error.call("ptr requires exactly one type argument") unless arguments.length == 1
533
+ error.call("ptr type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
534
+ when "const_ptr"
535
+ error.call("const_ptr requires exactly one type argument") unless arguments.length == 1
536
+ error.call("const_ptr type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
537
+ error.call("const_ptr cannot target ref types") if contains_ref_type?(arguments.first)
538
+ when "own"
539
+ error.call("own requires exactly one type argument") unless arguments.length == 1
540
+ error.call("own type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
541
+ when "ref"
542
+ unless [1, 2].include?(arguments.length)
543
+ error.call("ref requires exactly one type argument")
544
+ end
545
+ type_arg = arguments.length == 1 ? arguments.first : arguments[1]
546
+ error.call("ref type argument must be a type") if type_arg.is_a?(Types::LiteralTypeArg)
547
+ error.call("ref cannot target void") if type_arg.is_a?(Types::Primitive) && type_arg.void?
548
+ if contains_ref_type?(type_arg)
549
+ unless (type_arg.is_a?(Types::Struct) || type_arg.is_a?(Types::StructInstance)) && type_arg.lifetime_params&.any?
550
+ error.call("ref cannot target another ref type")
551
+ end
552
+ end
553
+ when "span"
554
+ error.call("span requires exactly one type argument") unless arguments.length == 1
555
+ error.call("span element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
556
+ when "array"
557
+ error.call("array requires exactly two type arguments") unless arguments.length == 2
558
+ error.call("array element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
559
+ error.call("array length must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments[1])
560
+ error.call("array length must be positive") if integer_type_argument?(arguments[1]) && !arguments[1].value.positive?
561
+ when "SoA"
562
+ error.call("SoA requires exactly two type arguments") unless arguments.length == 2
563
+ error.call("SoA element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
564
+ error.call("SoA element type must be a struct with fields") unless arguments.first.respond_to?(:fields) && arguments.first.fields.any?
565
+ error.call("SoA length must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments[1])
566
+ error.call("SoA length must be positive") if integer_type_argument?(arguments[1]) && !arguments[1].value.positive?
567
+ when "str_buffer"
568
+ error.call("str_buffer requires exactly one type argument") unless arguments.length == 1
569
+ error.call("str_buffer capacity must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments.first)
570
+ error.call("str_buffer capacity must be positive") if integer_type_argument?(arguments.first) && !arguments.first.value.positive?
571
+ when "Task"
572
+ error.call("Task requires exactly one type argument") unless arguments.length == 1
573
+ error.call("Task result type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
574
+ when "atomic"
575
+ error.call("atomic requires exactly one type argument") unless arguments.length == 1
576
+ arg = arguments.first
577
+ error.call("atomic type argument must be a type") if arg.is_a?(Types::LiteralTypeArg)
578
+ error.call("atomic type argument must be a primitive integer or bool") unless arg.is_a?(Types::Primitive) && (arg.integer? || arg.boolean?)
579
+ else
580
+ error.call("unknown generic type #{name}")
581
+ end
582
+ end
583
+
584
+ private
585
+
586
+ def char_array_text_type?(type)
587
+ return false unless array_type?(type)
588
+
589
+ element = array_element_type(type)
590
+ element.is_a?(Types::Primitive) && element.name == "char"
591
+ end
592
+
593
+ def str_buffer_type?(type)
594
+ type.arguments.length == 1 && type.arguments.first.is_a?(Types::LiteralTypeArg) && type.arguments.first.value.is_a?(Integer)
595
+ end
596
+
597
+ def array_type?(type)
598
+ type.arguments.length == 2 && type.arguments[1].is_a?(Types::LiteralTypeArg) && type.arguments[1].value.is_a?(Integer)
599
+ end
600
+
601
+ def array_length(type)
602
+ type.arguments[1].value
603
+ end
604
+
605
+ def array_element_type(type)
606
+ type.arguments.first
607
+ end
608
+ end
609
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ module Types
5
+ module Registry
6
+ @pool = {}
7
+ @mutex = Mutex.new
8
+
9
+ module_function
10
+
11
+ def reset!
12
+ @mutex.synchronize { @pool.clear }
13
+ end
14
+
15
+ def _intern(key, &construct)
16
+ @mutex.synchronize do
17
+ @pool[key] ||= construct.call
18
+ end
19
+ end
20
+
21
+ def primitive(name)
22
+ _intern([:primitive, name]) { Primitive.new(name) }
23
+ end
24
+
25
+ def nullable(base)
26
+ _intern([:nullable, base]) { Nullable.new(base) }
27
+ end
28
+
29
+ def generic_instance(name, arguments)
30
+ args = arguments.freeze
31
+ _intern([:generic, name, args]) { GenericInstance.new(name, args) }
32
+ end
33
+
34
+ def span(element_type)
35
+ _intern([:span, element_type]) { Span.new(element_type) }
36
+ end
37
+
38
+ def task(result_type)
39
+ _intern([:task, result_type]) { Task.new(result_type) }
40
+ end
41
+
42
+ def string_view
43
+ _intern([:string_view]) { StringView.new }
44
+ end
45
+
46
+ def function(name, params:, return_type:, receiver_type: nil, receiver_editable: false, variadic: false, external: false)
47
+ params_frozen = params.freeze
48
+ _intern([:function, name, params_frozen, return_type, receiver_type, receiver_editable, variadic, external]) {
49
+ Function.new(name, params: params_frozen, return_type: return_type, receiver_type: receiver_type, receiver_editable: receiver_editable, variadic: variadic, external: external)
50
+ }
51
+ end
52
+
53
+ def proc(params:, return_type:)
54
+ params_frozen = params.freeze
55
+ _intern([:proc, params_frozen, return_type]) { Proc.new(params: params_frozen, return_type: return_type) }
56
+ end
57
+
58
+ def parameter(name, type, mutable: false, passing_mode: :plain, boundary_type: nil)
59
+ _intern([:parameter, name, type, mutable, passing_mode, boundary_type]) {
60
+ Parameter.new(name, type, mutable: mutable, passing_mode: passing_mode, boundary_type: boundary_type)
61
+ }
62
+ end
63
+
64
+ def tuple(element_types, field_names: nil)
65
+ et_frozen = element_types.freeze
66
+ fn_frozen = field_names&.freeze
67
+ _intern([:tuple, et_frozen, fn_frozen]) { Tuple.new(et_frozen, field_names: fn_frozen) }
68
+ end
69
+
70
+ def soa(element_type, count:)
71
+ _intern([:soa, element_type, count]) { SoA.new(element_type, count: count) }
72
+ end
73
+
74
+ def lifetime_ref(name)
75
+ LifetimeRef.new(name)
76
+ end
77
+
78
+ def dyn(interface_binding, type_arguments = [])
79
+ Dyn.new(interface_binding, type_arguments)
80
+ end
81
+ end
82
+ end
83
+ end