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,442 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "predicates"
4
+
5
+ module MilkTea
6
+ class TypeVisitor
7
+ def initialize
8
+ @visited = {}
9
+ end
10
+
11
+ def visit(type)
12
+ return if type.nil?
13
+ return if @visited[type.object_id]
14
+
15
+ @visited[type.object_id] = true
16
+ dispatch(type)
17
+ end
18
+
19
+ def dispatch(type)
20
+ case type
21
+ when Types::Nullable then visit_nullable(type)
22
+ when Types::GenericInstance then visit_generic_instance(type)
23
+ when Types::Span then visit_span(type)
24
+ when Types::Task then visit_task(type)
25
+ when Types::GenericStructDefinition then visit_generic_struct_definition(type)
26
+ when Types::GenericVariantDefinition then visit_generic_variant_definition(type)
27
+ when Types::Struct then visit_struct(type)
28
+ when Types::Union then visit_union(type)
29
+ when Types::StructInstance then visit_struct_instance(type)
30
+ when Types::Variant then visit_variant(type)
31
+ when Types::VariantInstance then visit_variant_instance(type)
32
+ when Types::VariantArmPayload then visit_variant_arm_payload(type)
33
+ when Types::Proc then visit_proc(type)
34
+ when Types::Function then visit_function(type)
35
+ when Types::Parameter then visit_parameter(type)
36
+ when Types::TypeVar then visit_type_var(type)
37
+ when Types::Null then visit_null(type)
38
+ when Types::Tuple then visit_tuple(type)
39
+ when Types::Dyn then visit_dyn(type)
40
+ when Types::SoA then visit_soa(type)
41
+ when Types::Event then visit_event(type)
42
+ when Types::LifetimeRef then visit_lifetime_ref(type)
43
+ else visit_default(type)
44
+ end
45
+ end
46
+
47
+ def visit_children(type)
48
+ type.children.each { |child| visit(child) }
49
+ end
50
+
51
+ def visit_nullable(type); visit_children(type); end
52
+ def visit_generic_instance(type); visit_children(type); end
53
+ def visit_span(type); visit_children(type); end
54
+ def visit_task(type); visit_children(type); end
55
+ def visit_generic_struct_definition(type); visit_children(type); end
56
+ def visit_generic_variant_definition(type); visit_children(type); end
57
+ def visit_struct(type); visit_children(type); end
58
+ def visit_union(type); visit_children(type); end
59
+ def visit_struct_instance(type); visit_children(type); end
60
+ def visit_variant(type); visit_children(type); end
61
+ def visit_variant_instance(type); visit_children(type); end
62
+ def visit_variant_arm_payload(type); visit_children(type); end
63
+ def visit_proc(type); visit_children(type); end
64
+ def visit_function(type); visit_children(type); end
65
+ def visit_parameter(type); visit_children(type); end
66
+ def visit_tuple(type); visit_children(type); end
67
+ def visit_dyn(type); visit_children(type); end
68
+ def visit_soa(type); visit_children(type); end
69
+ def visit_event(type); visit_children(type); end
70
+
71
+ def visit_type_var(type); end
72
+ def visit_null(type); end
73
+ def visit_lifetime_ref(type); end
74
+ def visit_default(type); end
75
+ end
76
+
77
+ class ContainsTypeVarVisitor < TypeVisitor
78
+ def initialize
79
+ super
80
+ @found = false
81
+ end
82
+
83
+ def found?
84
+ @found
85
+ end
86
+
87
+ def visit_type_var(type)
88
+ @found = true
89
+ end
90
+ end
91
+
92
+ class ContainsRefTypeVisitor < TypeVisitor
93
+ def initialize(allow_lifetimes: [])
94
+ super()
95
+ @found = false
96
+ @allow_lifetimes = allow_lifetimes
97
+ end
98
+
99
+ def found?
100
+ @found
101
+ end
102
+
103
+ def visit_generic_instance(type)
104
+ if type.name == "ref" && [1, 2].include?(type.arguments.length)
105
+ if type.arguments.length == 2
106
+ lt = type.arguments.first
107
+ if lt.is_a?(String) && @allow_lifetimes.include?(lt)
108
+ visit_children(type)
109
+ return
110
+ end
111
+ end
112
+ @found = true
113
+ return
114
+ end
115
+ visit_children(type)
116
+ end
117
+ end
118
+
119
+ class ContainsProcTypeVisitor < TypeVisitor
120
+ def initialize
121
+ super
122
+ @found = false
123
+ end
124
+
125
+ def found?
126
+ @found
127
+ end
128
+
129
+ def visit_proc(type)
130
+ @found = true
131
+ end
132
+
133
+ def visit_generic_instance(type)
134
+ if type.name == "array" && type.arguments.first && !type.arguments.first.is_a?(Types::LiteralTypeArg)
135
+ visit(type.arguments.first)
136
+ end
137
+ end
138
+ end
139
+
140
+ class ContainsCallableRefTypeVisitor < TypeVisitor
141
+ def initialize
142
+ super
143
+ @found = false
144
+ end
145
+
146
+ def found?
147
+ @found
148
+ end
149
+
150
+ def visit_proc(type)
151
+ checker = ContainsRefTypeVisitor.new
152
+ checker.visit(type)
153
+ @found = true if checker.found?
154
+ end
155
+ alias visit_function visit_proc
156
+ end
157
+
158
+ class StoredRefSupportedVisitor < TypeVisitor
159
+ include TypePredicates
160
+
161
+ def initialize(allow_lifetimes: [])
162
+ super()
163
+ @supported = true
164
+ @allow_lifetimes = allow_lifetimes
165
+ end
166
+
167
+ def result?
168
+ @supported
169
+ end
170
+
171
+ def visit_generic_instance(type)
172
+ if ref_type?(type)
173
+ lt = ref_lifetime(type)
174
+ if lt && @allow_lifetimes.include?(lt)
175
+ visit_children(type)
176
+ return
177
+ end
178
+ @supported = false
179
+ return
180
+ end
181
+ visit_children(type)
182
+ end
183
+
184
+ def visit_proc(type)
185
+ @supported = false unless callable_param_ref_supported?(type)
186
+ end
187
+ alias visit_function visit_proc
188
+
189
+ private
190
+
191
+ def visit_children(type)
192
+ type.children.each do |child|
193
+ visit(child)
194
+ return unless @supported
195
+ end
196
+ end
197
+ end
198
+
199
+ class SendableCheckVisitor < TypeVisitor
200
+ def initialize
201
+ super
202
+ @sendable = true
203
+ end
204
+
205
+ def sendable?
206
+ @sendable
207
+ end
208
+
209
+ def visit_children(type)
210
+ type.children.each do |child|
211
+ visit(child)
212
+ return unless @sendable
213
+ end
214
+ end
215
+
216
+ def visit_event(type)
217
+ @sendable = false
218
+ end
219
+
220
+ def visit_dyn(type)
221
+ @sendable = false
222
+ end
223
+
224
+ def visit_span(type)
225
+ @sendable = false
226
+ end
227
+
228
+ def visit_proc(type)
229
+ @sendable = false
230
+ end
231
+
232
+ def visit_function(type); end
233
+
234
+ def visit_generic_instance(type)
235
+ case type.name
236
+ when "ptr", "const_ptr", "own", "ref"
237
+ @sendable = false
238
+ when "array"
239
+ el = type.arguments.first
240
+ visit(el) unless el.is_a?(Types::LiteralTypeArg)
241
+ when "str_buffer", "atomic"
242
+ # sendable
243
+ else
244
+ @sendable = false
245
+ end
246
+ end
247
+
248
+ def visit_struct(type)
249
+ if type.respond_to?(:has_events?) && type.has_events?
250
+ @sendable = false
251
+ return
252
+ end
253
+ visit_children(type)
254
+ end
255
+ alias visit_struct_instance visit_struct
256
+
257
+ def visit_default(type)
258
+ case type
259
+ when Types::Primitive
260
+ @sendable = false if type.name == "str"
261
+ when Types::Error, Types::Opaque, Types::StringView
262
+ @sendable = false
263
+ end
264
+ end
265
+ end
266
+
267
+ class SubstituteTypeVisitor
268
+ def initialize(substitutions)
269
+ @substitutions = substitutions
270
+ end
271
+
272
+ def apply(type)
273
+ case type
274
+ when Types::TypeVar
275
+ @substitutions.fetch(type.name, type)
276
+ when Types::LifetimeRef
277
+ @substitutions.fetch(type.name, type)
278
+ when Types::Nullable
279
+ substituted = apply(type.base)
280
+ substituted.equal?(type.base) ? type : Types::Registry.nullable(substituted)
281
+ when Types::GenericInstance
282
+ new_args = type.arguments.map do |arg|
283
+ arg.is_a?(Types::LiteralTypeArg) ? arg : apply(arg)
284
+ end
285
+ type.arguments.zip(new_args).all? { |old, new| old.equal?(new) } ? type : Types::Registry.generic_instance(type.name, new_args)
286
+ when Types::Span
287
+ substituted = apply(type.element_type)
288
+ substituted.equal?(type.element_type) ? type : Types::Registry.span(substituted)
289
+ when Types::Task
290
+ substituted = apply(type.result_type)
291
+ substituted.equal?(type.result_type) ? type : Types::Registry.task(substituted)
292
+ when Types::Event
293
+ new_payload = type.payload_type ? apply(type.payload_type) : nil
294
+ if new_payload.equal?(type.payload_type)
295
+ type
296
+ else
297
+ Types::Event.new(type.name, capacity: type.capacity, payload_type: new_payload, module_name: type.module_name, visibility: type.visibility, owner_type_name: type.owner_type_name)
298
+ end
299
+ when Types::Proc
300
+ changed = false
301
+ new_params = type.params.map do |param|
302
+ new_param_type = apply(param.type)
303
+ new_boundary = param.boundary_type ? apply(param.boundary_type) : nil
304
+ changed = true unless new_param_type.equal?(param.type) && new_boundary.equal?(param.boundary_type)
305
+ Types::Registry.parameter(param.name, new_param_type, mutable: param.mutable, passing_mode: param.passing_mode, boundary_type: new_boundary)
306
+ end
307
+ new_return = apply(type.return_type)
308
+ changed = true unless new_return.equal?(type.return_type)
309
+ changed ? Types::Registry.proc(params: new_params, return_type: new_return) : type
310
+ when Types::Function
311
+ changed = false
312
+ new_params = type.params.map do |param|
313
+ new_param_type = apply(param.type)
314
+ new_boundary = param.boundary_type ? apply(param.boundary_type) : nil
315
+ changed = true unless new_param_type.equal?(param.type) && new_boundary.equal?(param.boundary_type)
316
+ Types::Registry.parameter(param.name, new_param_type, mutable: param.mutable, passing_mode: param.passing_mode, boundary_type: new_boundary)
317
+ end
318
+ new_return = apply(type.return_type)
319
+ changed = true unless new_return.equal?(type.return_type)
320
+ new_receiver = type.receiver_type ? apply(type.receiver_type) : nil
321
+ changed = true unless new_receiver.equal?(type.receiver_type)
322
+ changed ? Types::Registry.function(type.name, params: new_params, return_type: new_return, receiver_type: new_receiver, receiver_editable: type.receiver_editable, variadic: type.variadic, external: type.external) : type
323
+ when Types::StructInstance
324
+ new_args = type.arguments.map { |arg| apply(arg) }
325
+ type.arguments.zip(new_args).all? { |old, new| old.equal?(new) } ? type : type.definition.instantiate(new_args)
326
+ when Types::VariantInstance
327
+ new_args = type.arguments.map { |arg| apply(arg) }
328
+ type.arguments.zip(new_args).all? { |old, new| old.equal?(new) } ? type : type.definition.instantiate(new_args)
329
+ else
330
+ type
331
+ end
332
+ end
333
+ end
334
+
335
+ class ContainsArrayStorageVisitor < TypeVisitor
336
+ def initialize
337
+ super
338
+ @found = false
339
+ end
340
+
341
+ def found?
342
+ @found
343
+ end
344
+
345
+ def dispatch(type)
346
+ case type
347
+ when Types::Nullable, Types::Struct, Types::StructInstance
348
+ visit_children(type)
349
+ when Types::GenericInstance
350
+ if type.name == "array"
351
+ @found = true
352
+ end
353
+ end
354
+ end
355
+
356
+ def visit_children(type)
357
+ type.children.each do |child|
358
+ visit(child)
359
+ return if @found
360
+ end
361
+ end
362
+ end
363
+
364
+ class ProcStorageSupportedVisitor < TypeVisitor
365
+ def initialize
366
+ super
367
+ @supported = true
368
+ end
369
+
370
+ def result?
371
+ @supported
372
+ end
373
+
374
+ def dispatch(type)
375
+ case type
376
+ when Types::Nullable, Types::GenericInstance, Types::Struct, Types::Union,
377
+ Types::StructInstance, Types::Variant, Types::VariantInstance, Types::VariantArmPayload,
378
+ Types::Tuple, Types::Span
379
+ visit_children(type)
380
+ when Types::Proc
381
+ when Types::Task, Types::Function, Types::Dyn, Types::SoA
382
+ @supported = false
383
+ end
384
+ end
385
+
386
+ def visit_children(type)
387
+ type.children.each do |child|
388
+ visit(child)
389
+ return unless @supported
390
+ end
391
+ end
392
+ end
393
+
394
+ class ValidateSpecializedTypeVisitor < TypeVisitor
395
+ def initialize(function_name:, context:, on_error:, on_generic_instance: nil)
396
+ super()
397
+ @function_name = function_name
398
+ @context = context
399
+ @on_error = on_error
400
+ @on_generic_instance = on_generic_instance
401
+ end
402
+
403
+ def visit_type_var(type)
404
+ @on_error.call("cannot infer type argument #{type.name} for function #{@function_name}")
405
+ end
406
+
407
+ def visit_generic_instance(type)
408
+ @on_generic_instance&.call(type.name, type.arguments)
409
+ visit_children(type)
410
+ end
411
+
412
+ def visit_proc(type)
413
+ type.params.each do |param|
414
+ with_context("#{@context} parameter #{param.name}") { visit(param.type) }
415
+ end
416
+ with_context("#{@context} return type") { visit(type.return_type) }
417
+ end
418
+
419
+ def visit_function(type)
420
+ type.params.each do |param|
421
+ with_context("#{@context} parameter #{param.name}") { visit(param.type) }
422
+ if param.boundary_type
423
+ with_context("#{@context} boundary parameter #{param.name}") { visit(param.boundary_type) }
424
+ end
425
+ end
426
+ with_context("#{@context} return type") { visit(type.return_type) }
427
+ if type.receiver_type
428
+ with_context("#{@context} receiver type") { visit(type.receiver_type) }
429
+ end
430
+ end
431
+
432
+ private
433
+
434
+ def with_context(new_context)
435
+ old = @context
436
+ @context = new_context
437
+ yield
438
+ ensure
439
+ @context = old
440
+ end
441
+ end
442
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ require_relative "core/keywords"
6
+ require_relative "core/token"
7
+ require_relative "core/token_stream"
8
+ require_relative "core/lexer"
9
+ require_relative "core/cst"
10
+ require_relative "core/cst_builder"
11
+ require_relative "core/ast"
12
+ require_relative "core/types/types"
13
+ require_relative "core/binding_types"
14
+ require_relative "core/compile_time"
15
+ require_relative "core/compatibility_helpers"
16
+ require_relative "core/parser"
17
+ require_relative "core/module_roots"
18
+ require_relative "core/module_loader"
19
+ require_relative "core/semantic_analyzer"
20
+ require_relative "core/ir"
21
+ require_relative "core/control_flow"
22
+ require_relative "core/pretty_printer"
23
+ require_relative "core/lowering"
24
+ # Codegen wrapper deleted; use CBackend.emit directly
25
+ require_relative "core/c_backend"
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+ require "thread"
5
+ require "timeout"
6
+
7
+ module MilkTea
8
+ module DAP
9
+ module Backends
10
+ # Thin bridge to an lldb-dap compatible adapter process.
11
+ class LLDBDAP
12
+ def initialize(adapter_command: ["lldb-dap"], on_event: nil, on_request: nil)
13
+ @adapter_command = adapter_command
14
+ @on_event = on_event
15
+ @on_request = on_request
16
+ @protocol = nil
17
+ @stdin = nil
18
+ @stdout = nil
19
+ @stderr = nil
20
+ @wait_thread = nil
21
+ @reader_thread = nil
22
+ @stderr_thread = nil
23
+ @write_mutex = Mutex.new
24
+ @pending_mutex = Mutex.new
25
+ @pending = {}
26
+ @next_seq = 1
27
+ end
28
+
29
+ def start!
30
+ return if running?
31
+
32
+ @stdin, @stdout, @stderr, @wait_thread = Open3.popen3(*@adapter_command)
33
+ @protocol = Protocol.new(input: @stdout, output: @stdin)
34
+
35
+ @reader_thread = Thread.new { read_loop }
36
+ @stderr_thread = Thread.new { drain_stderr }
37
+ end
38
+
39
+ def running?
40
+ !@wait_thread.nil? && @wait_thread.alive?
41
+ end
42
+
43
+ def request(command, arguments = {}, timeout: 5)
44
+ start! unless running?
45
+
46
+ seq = next_seq
47
+ queue = Queue.new
48
+ @pending_mutex.synchronize do
49
+ @pending[seq] = queue
50
+ end
51
+
52
+ @write_mutex.synchronize do
53
+ @protocol.write_message({
54
+ seq: seq,
55
+ type: "request",
56
+ command: command,
57
+ arguments: arguments
58
+ })
59
+ end
60
+
61
+ Timeout.timeout(timeout) { queue.pop }
62
+ rescue Timeout::Error
63
+ {
64
+ "type" => "response",
65
+ "request_seq" => seq,
66
+ "success" => false,
67
+ "message" => "backend request timed out: #{command}"
68
+ }
69
+ ensure
70
+ @pending_mutex.synchronize { @pending.delete(seq) }
71
+ end
72
+
73
+ def stop!
74
+ @stdin&.close
75
+ @stdout&.close
76
+ @stderr&.close
77
+ if @wait_thread&.alive?
78
+ Process.kill("TERM", @wait_thread.pid)
79
+ end
80
+ rescue StandardError
81
+ nil
82
+ ensure
83
+ @wait_thread&.join(0.2)
84
+ @reader_thread&.join(0.2)
85
+ @stderr_thread&.join(0.2)
86
+ @stdin = nil
87
+ @stdout = nil
88
+ @stderr = nil
89
+ @wait_thread = nil
90
+ @reader_thread = nil
91
+ @stderr_thread = nil
92
+ end
93
+
94
+ private
95
+
96
+ def next_seq
97
+ seq = @next_seq
98
+ @next_seq += 1
99
+ seq
100
+ end
101
+
102
+ def read_loop
103
+ loop do
104
+ message = @protocol.read_message
105
+ break if message.nil?
106
+
107
+ if message["type"] == "response"
108
+ queue = @pending_mutex.synchronize { @pending[message["request_seq"]] }
109
+ queue&.push(message)
110
+ elsif message["type"] == "event"
111
+ @on_event&.call(message)
112
+ elsif message["type"] == "request"
113
+ handle_adapter_request(message)
114
+ end
115
+ end
116
+ rescue StandardError
117
+ nil
118
+ ensure
119
+ @pending_mutex.synchronize do
120
+ @pending.each_value do |queue|
121
+ queue.push({
122
+ "type" => "response",
123
+ "success" => false,
124
+ "message" => "backend closed"
125
+ })
126
+ end
127
+ @pending.clear
128
+ end
129
+ end
130
+
131
+ def drain_stderr
132
+ return unless @stderr
133
+
134
+ @stderr.each_line do |_line|
135
+ # Intentionally ignored in this bridge layer.
136
+ end
137
+ rescue StandardError
138
+ nil
139
+ end
140
+
141
+ def handle_adapter_request(message)
142
+ response = @on_request&.call(message)
143
+ response ||= {
144
+ "type" => "response",
145
+ "request_seq" => message["seq"],
146
+ "success" => false,
147
+ "command" => message["command"],
148
+ "message" => "unsupported reverse request: #{message['command']}"
149
+ }
150
+
151
+ @write_mutex.synchronize do
152
+ @protocol.write_message(response)
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module MilkTea
6
+ module DAP
7
+ # Handles DAP framing over stdin/stdout using Content-Length headers.
8
+ class Protocol
9
+ INVALID_MESSAGE = Object.new.freeze
10
+
11
+ def initialize(input: $stdin, output: $stdout, error_output: nil)
12
+ @input = input
13
+ @output = output
14
+ @error_output = error_output
15
+ end
16
+
17
+ def read_message
18
+ headers = {}
19
+ loop do
20
+ line = @input.gets
21
+ return nil if line.nil?
22
+
23
+ stripped = line.chomp
24
+ break if stripped.empty?
25
+
26
+ key, value = stripped.split(":", 2)
27
+ headers[key&.strip] = value&.strip
28
+ end
29
+
30
+ content_length = headers["Content-Length"]&.to_i
31
+ return INVALID_MESSAGE if content_length.nil? || content_length <= 0
32
+
33
+ body = @input.read(content_length)
34
+ JSON.parse(body)
35
+ rescue StandardError => e
36
+ log_error("DAP protocol read error: #{e.message}")
37
+ INVALID_MESSAGE
38
+ end
39
+
40
+ def write_message(message)
41
+ json = JSON.dump(message)
42
+ @output.write("Content-Length: #{json.bytesize}\r\n\r\n")
43
+ @output.write(json)
44
+ @output.flush
45
+ rescue StandardError => e
46
+ log_error("DAP protocol write error: #{e.message}")
47
+ end
48
+
49
+ private def log_error(message)
50
+ return unless @error_output
51
+
52
+ @error_output.puts(message)
53
+ rescue StandardError
54
+ nil
55
+ end
56
+ end
57
+ end
58
+ end