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,311 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ module AST
5
+ class QualifiedName < Data.define(:parts, :type_arguments, :line, :column)
6
+ def initialize(parts:, type_arguments: [], line: nil, column: nil) = super
7
+ def to_s
8
+ parts.join(".")
9
+ end
10
+ end
11
+
12
+ TypeParamConstraint = Data.define(:kind, :interface_ref) do
13
+ def initialize(kind:, interface_ref: nil) = super
14
+ end
15
+
16
+ TypeParam = Data.define(:name, :constraints, :line, :column, :length) do
17
+ def initialize(name:, constraints: [], line: nil, column: nil, length: nil) = super
18
+ end
19
+ ValueTypeParam = Data.define(:name, :type, :line, :column, :length) do
20
+ def initialize(name:, type:, line: nil, column: nil, length: nil) = super
21
+ end
22
+ TypeArgument = Data.define(:value)
23
+ class TypeRef < Data.define(:name, :arguments, :nullable, :lifetime, :line, :column, :length)
24
+ def initialize(name:, arguments:, nullable:, lifetime: nil, line: nil, column: nil, length: nil) = super
25
+
26
+ def to_s
27
+ text = name.to_s
28
+ args = []
29
+ args << lifetime if lifetime
30
+ args.concat(arguments.map do |argument|
31
+ value = argument.value
32
+ case value
33
+ when IntegerLiteral, FloatLiteral then value.lexeme
34
+ else value.to_s
35
+ end
36
+ end)
37
+ unless args.empty?
38
+ text += "[#{args.join(', ')}]"
39
+ end
40
+ nullable ? "#{text}?" : text
41
+ end
42
+ end
43
+ FunctionType = Data.define(:params, :return_type)
44
+ ProcType = Data.define(:params, :return_type)
45
+ TupleType = Data.define(:element_types, :nullable) do
46
+ def initialize(element_types:, nullable: false) = super
47
+ end
48
+ DynType = Data.define(:interface, :nullable, :line, :column, :length) do
49
+ def initialize(interface:, nullable: false, line: nil, column: nil, length: nil) = super
50
+ end
51
+ SourceFile = Data.define(:module_name, :module_kind, :imports, :directives, :declarations, :line, :node_ids, :node_path_ids) do
52
+ def initialize(module_name:, module_kind:, imports:, directives:, declarations:, line: nil, node_ids: {}, node_path_ids: {}) = super
53
+ end
54
+ Import = Data.define(:path, :alias_name, :line, :column, :length) do
55
+ def initialize(path:, alias_name:, line: nil, column: nil, length: nil) = super
56
+ end
57
+ LinkDirective = Data.define(:value)
58
+ IncludeDirective = Data.define(:value)
59
+ CompilerFlagDirective = Data.define(:value)
60
+ ConstDecl = Data.define(:name, :type, :value, :block_body, :visibility, :attributes, :line, :column) do
61
+ def initialize(name:, type:, value:, block_body: nil, visibility:, attributes: [], line: nil, column: nil) = super
62
+ end
63
+ VarDecl = Data.define(:name, :type, :value, :visibility, :line, :column) do
64
+ def initialize(name:, type:, value:, visibility:, line: nil, column: nil) = super
65
+ end
66
+ EventDecl = Data.define(:name, :capacity, :payload_type, :visibility, :attributes, :line, :column) do
67
+ def initialize(name:, capacity:, payload_type: nil, visibility:, attributes: [], line: nil, column: nil) = super
68
+ end
69
+ TypeAliasDecl = Data.define(:name, :target, :visibility, :line, :column) do
70
+ def initialize(name:, target:, visibility:, line: nil, column: nil) = super
71
+ end
72
+ AttributeDecl = Data.define(:name, :targets, :params, :visibility, :line, :column) do
73
+ def initialize(name:, targets:, params:, visibility:, line: nil, column: nil) = super
74
+ end
75
+ AttributeApplication = Data.define(:name, :arguments, :line, :column) do
76
+ def initialize(name:, arguments:, line: nil, column: nil) = super
77
+ end
78
+ StructDecl = Data.define(:name, :type_params, :implements, :c_name, :fields, :events, :nested_types, :attributes, :packed, :alignment, :visibility, :lifetime_params, :line, :column) do
79
+ def initialize(name:, type_params:, implements:, c_name:, fields:, events: [], nested_types: [], attributes: [], packed:, alignment:, visibility:, lifetime_params: [], line: nil, column: nil) = super
80
+ end
81
+ UnionDecl = Data.define(:name, :c_name, :fields, :visibility, :attributes, :line, :column) do
82
+ def initialize(name:, c_name:, fields:, visibility:, attributes: [], line: nil, column: nil) = super
83
+ end
84
+ Field = Data.define(:name, :type, :attributes, :line, :column) do
85
+ def initialize(name:, type:, attributes: [], line: nil, column: nil) = super
86
+ end
87
+ EnumDecl = Data.define(:name, :backing_type, :members, :visibility, :attributes, :line, :column) do
88
+ def initialize(name:, backing_type:, members:, visibility:, attributes: [], line: nil, column: nil) = super
89
+ end
90
+ FlagsDecl = Data.define(:name, :backing_type, :members, :visibility, :attributes, :line, :column) do
91
+ def initialize(name:, backing_type:, members:, visibility:, attributes: [], line: nil, column: nil) = super
92
+ end
93
+ EnumMember = Data.define(:name, :value, :line, :column) do
94
+ def initialize(name:, value:, line: nil, column: nil) = super
95
+ end
96
+ OpaqueDecl = Data.define(:name, :implements, :c_name, :visibility, :line, :column) do
97
+ def initialize(name:, implements:, c_name:, visibility:, line: nil, column: nil) = super
98
+ end
99
+ InterfaceDecl = Data.define(:name, :type_params, :methods, :visibility, :line, :column) do
100
+ def initialize(name:, type_params: [], methods:, visibility:, line: nil, column: nil) = super
101
+ end
102
+ ExtendingBlock = Data.define(:type_name, :methods, :line, :column) do
103
+ def initialize(type_name:, methods:, line: nil, column: nil) = super
104
+ end
105
+ InterfaceMethodDecl = Data.define(:name, :params, :return_type, :kind, :async, :attributes, :line, :column) do
106
+ def initialize(name:, params:, return_type:, kind:, async:, attributes: [], line: nil, column: nil) = super
107
+ end
108
+ FunctionDef = Data.define(:name, :type_params, :params, :return_type, :body, :visibility, :async, :const, :attributes, :line, :column) do
109
+ def initialize(name:, type_params:, params:, return_type:, body:, visibility:, async:, const: false, attributes: [], line: nil, column: nil) = super
110
+ end
111
+ MethodDef = Data.define(:name, :type_params, :params, :return_type, :body, :kind, :visibility, :async, :attributes, :line, :column) do
112
+ def initialize(name:, type_params:, params:, return_type:, body:, kind:, visibility:, async:, attributes: [], line: nil, column: nil) = super
113
+ end
114
+ ExternFunctionDecl = Data.define(:name, :type_params, :params, :return_type, :variadic, :attributes, :line, :mapping) do
115
+ def initialize(name:, type_params:, params:, return_type:, variadic:, attributes: [], line: nil, mapping: nil) = super
116
+ end
117
+ ForeignFunctionDecl = Data.define(:name, :type_params, :params, :return_type, :variadic, :mapping, :visibility, :attributes, :line) do
118
+ def initialize(name:, type_params:, params:, return_type:, variadic:, mapping:, visibility:, attributes: [], line: nil) = super
119
+ end
120
+ Param = Data.define(:name, :type, :line, :column) do
121
+ def initialize(name:, type:, line: nil, column: nil) = super
122
+ end
123
+ ForeignParam = Data.define(:name, :type, :mode, :boundary_type)
124
+ LocalDecl = Data.define(:kind, :name, :type, :value, :else_binding, :else_body, :line, :column, :recovered_else, :destructure_bindings, :destructure_type_name) do
125
+ def initialize(kind:, name:, type:, value:, else_binding: nil, else_body: nil, line: nil, column: nil, recovered_else: false, destructure_bindings: nil, destructure_type_name: nil) = super
126
+ end
127
+ Assignment = Data.define(:target, :operator, :value, :line, :column) do
128
+ def initialize(target:, operator:, value:, line: nil, column: nil) = super
129
+ end
130
+ IfBranch = Data.define(:condition, :body, :line, :column, :length) do
131
+ def initialize(condition:, body:, line: nil, column: nil, length: nil) = super
132
+ end
133
+ IfStmt = Data.define(:branches, :else_body, :inline, :line, :else_line, :else_column) do
134
+ def initialize(branches:, else_body:, inline: false, line: nil, else_line: nil, else_column: nil) = super
135
+ end
136
+ VariantDecl = Data.define(:name, :type_params, :arms, :visibility, :attributes, :line, :column) do
137
+ def initialize(name:, type_params:, arms:, visibility:, attributes: [], line: nil, column: nil) = super
138
+ end
139
+ VariantArm = Data.define(:name, :fields)
140
+ MatchArm = Data.define(:pattern, :binding_name, :binding_line, :binding_column, :body) do
141
+ def initialize(pattern:, binding_name:, body:, binding_line: nil, binding_column: nil) = super
142
+ end
143
+ MatchStmt = Data.define(:expression, :arms, :inline, :line, :column, :length) do
144
+ def initialize(expression:, arms:, inline: false, line: nil, column: nil, length: nil) = super
145
+ end
146
+ MatchExprArm = Data.define(:pattern, :binding_name, :binding_line, :binding_column, :value) do
147
+ def initialize(pattern:, binding_name:, value:, binding_line: nil, binding_column: nil) = super
148
+ end
149
+ WhenBranch = Data.define(:pattern, :binding_name, :binding_line, :binding_column, :body) do
150
+ def initialize(pattern:, binding_name:, body:, binding_line: nil, binding_column: nil) = super
151
+ end
152
+ WhenStmt = Data.define(:discriminant, :branches, :else_body, :line, :column, :length) do
153
+ def initialize(discriminant:, branches:, else_body:, line: nil, column: nil, length: nil) = super
154
+ end
155
+ UnsafeStmt = Data.define(:body, :line, :column, :length) do
156
+ def initialize(body:, line: nil, column: nil, length: nil) = super
157
+ end
158
+ StaticAssert = Data.define(:condition, :message, :line) do
159
+ def initialize(condition:, message:, line: nil) = super
160
+ end
161
+ EmitStmt = Data.define(:declaration, :line, :column) do
162
+ def initialize(declaration:, line: nil, column: nil) = super
163
+ end
164
+ ForBinding = Data.define(:name, :line, :column) do
165
+ def initialize(name:, line: nil, column: nil) = super
166
+ end
167
+ ForStmt = Data.define(:bindings, :iterables, :body, :inline, :threaded, :line, :column) do
168
+ def initialize(bindings:, iterables:, body:, inline: false, threaded: false, line: nil, column: nil) = super
169
+ def name = bindings.first.name
170
+ def names = bindings.map(&:name)
171
+ def binding = bindings.first
172
+ def iterable = iterables.first
173
+ def parallel? = bindings.length > 1 || iterables.length > 1
174
+ end
175
+ ParallelBlockStmt = Data.define(:bodies, :line, :column) do
176
+ def initialize(bodies:, line: nil, column: nil) = super
177
+ end
178
+ DetachExpr = Data.define(:body, :line, :column) do
179
+ def initialize(body:, line: nil, column: nil) = super
180
+ end
181
+ GatherStmt = Data.define(:handles, :line, :column) do
182
+ def initialize(handles:, line: nil, column: nil) = super
183
+ end
184
+ WhileStmt = Data.define(:condition, :body, :inline, :line, :column, :length) do
185
+ def initialize(condition:, body:, inline: false, line: nil, column: nil, length: nil) = super
186
+ end
187
+ BreakStmt = Data.define(:line, :column, :length) do
188
+ def initialize(line: nil, column: nil, length: nil) = super
189
+ end
190
+ ContinueStmt = Data.define(:line, :column, :length) do
191
+ def initialize(line: nil, column: nil, length: nil) = super
192
+ end
193
+ PassStmt = Data.define(:line, :column, :length) do
194
+ def initialize(line: nil, column: nil, length: nil) = super
195
+ end
196
+ ReturnStmt = Data.define(:value, :line, :column, :length) do
197
+ def initialize(value:, line: nil, column: nil, length: nil) = super
198
+ end
199
+ DeferStmt = Data.define(:expression, :body, :line, :column, :length) do
200
+ def initialize(expression:, body:, line: nil, column: nil, length: nil) = super
201
+ end
202
+ ErrorBlockStmt = Data.define(:body, :line, :column, :length, :message, :header_type, :header_expression, :header_bindings, :header_iterables) do
203
+ def initialize(body:, line: nil, column: nil, length: nil, message: nil, header_type: nil, header_expression: nil, header_bindings: nil, header_iterables: nil) = super
204
+ end
205
+ ErrorStmt = Data.define(:line, :column, :length, :message) do
206
+ def initialize(line: nil, column: nil, length: nil, message: nil) = super
207
+ end
208
+ ErrorExpr = Data.define(:line, :column, :length, :message) do
209
+ def initialize(line: nil, column: nil, length: nil, message: nil) = super
210
+ end
211
+ ExpressionStmt = Data.define(:expression, :line) do
212
+ def initialize(expression:, line: nil) = super
213
+ end
214
+
215
+ Identifier = Data.define(:name, :line, :column) do
216
+ def initialize(name:, line: nil, column: nil) = super
217
+ end
218
+ MemberAccess = Data.define(:receiver, :member, :line, :column) do
219
+ def initialize(receiver:, member:, line: nil, column: nil) = super
220
+ end
221
+ IndexAccess = Data.define(:receiver, :index)
222
+ Specialization = Data.define(:callee, :arguments)
223
+ Call = Data.define(:callee, :arguments)
224
+ Argument = Data.define(:name, :value)
225
+ UnaryOp = Data.define(:operator, :operand)
226
+ BinaryOp = Data.define(:operator, :left, :right)
227
+ RangeExpr = Data.define(:start_expr, :end_expr, :line, :column)
228
+ ExpressionList = Data.define(:elements, :line, :column)
229
+ IfExpr = Data.define(:condition, :then_expression, :else_expression)
230
+ MatchExpr = Data.define(:expression, :arms, :line, :column, :length) do
231
+ def initialize(expression:, arms:, line: nil, column: nil, length: nil) = super
232
+ end
233
+ UnsafeExpr = Data.define(:expression, :line, :column, :length) do
234
+ def initialize(expression:, line: nil, column: nil, length: nil) = super
235
+ end
236
+ ProcExpr = Data.define(:params, :return_type, :body)
237
+ AwaitExpr = Data.define(:expression)
238
+ SizeofExpr = Data.define(:type)
239
+ AlignofExpr = Data.define(:type)
240
+ OffsetofExpr = Data.define(:type, :field)
241
+ IntegerLiteral = Data.define(:lexeme, :value)
242
+ FloatLiteral = Data.define(:lexeme, :value)
243
+ StringLiteral = Data.define(:lexeme, :value, :cstring)
244
+ FormatString = Data.define(:parts)
245
+ FormatTextPart = Data.define(:value)
246
+ FormatExprPart = Data.define(:expression, :format_spec)
247
+ CharLiteral = Data.define(:lexeme, :value, :line, :column) do
248
+ def initialize(lexeme:, value:, line: nil, column: nil) = super
249
+ end
250
+ BooleanLiteral = Data.define(:value)
251
+ NullLiteral = Data.define(:type, :line, :column) do
252
+ def initialize(type:, line: nil, column: nil) = super
253
+ end
254
+ PrefixCast = Data.define(:target_type, :expression, :line, :column, :length) do
255
+ def initialize(target_type:, expression:, line: nil, column: nil, length: nil) = super
256
+ end
257
+
258
+ def self.assign_node_ids(source_file)
259
+ next_id = 0
260
+ node_ids = {}
261
+ path_ids = {}
262
+
263
+ visit = ->(node, path = "") do
264
+ return [next_id, path] unless node.is_a?(::Data)
265
+
266
+ node_ids[node.object_id] = (next_id += 1)
267
+ current_path = path.empty? ? node.class.name.sub(/\AMilkTea::AST::/, "") : path
268
+ path_ids[current_path] = node_ids[node.object_id]
269
+
270
+ if node.respond_to?(:declarations) && node.declarations.is_a?(Array)
271
+ node.declarations.each_with_index { |d, i| visit.call(d, "#{current_path}.declarations[#{i}]") }
272
+ end
273
+
274
+ if node.respond_to?(:body)
275
+ visit.call(node.body, "#{current_path}.body")
276
+ end
277
+
278
+ node.class.members.each do |field_name|
279
+ next if %i[module_name module_kind].include?(field_name)
280
+
281
+ value = node.public_send(field_name)
282
+ next unless value
283
+
284
+ field_path = "#{current_path}.#{field_name}"
285
+
286
+ case value
287
+ when ::Data
288
+ visit.call(value, field_path)
289
+ when Array
290
+ value.each_with_index do |v, i|
291
+ visit.call(v, "#{field_path}[#{i}]") if v.is_a?(::Data)
292
+ end
293
+ end
294
+ end
295
+ end
296
+
297
+ visit.call(source_file)
298
+ source_file.with(node_ids: node_ids.freeze, node_path_ids: path_ids.freeze)
299
+ end
300
+
301
+ def self.build_chain_from_parts(parts)
302
+ return nil unless parts.length >= 1
303
+
304
+ expr = Identifier.new(name: parts.first)
305
+ parts[1..].each do |part|
306
+ expr = MemberAccess.new(receiver: expr, member: part)
307
+ end
308
+ expr
309
+ end
310
+ end
311
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ class AsyncRuntimeInstaller
5
+ def initialize(resolve_module_path:, check_block:, bind_block:)
6
+ @resolve_module_path = resolve_module_path
7
+ @check_block = check_block
8
+ @bind_block = bind_block
9
+ end
10
+
11
+ def install_async_runtime_dependency!(ast, modules, importer_path: nil, collecting_errors: false)
12
+ return if modules.key?("std.async")
13
+ return unless async_main_declared?(ast)
14
+
15
+ import_path = @resolve_module_path.call("std.async", importer_path:)
16
+ import_analysis = @check_block.call(import_path, collecting_errors)
17
+ modules["std.async"] = @bind_block.call(import_analysis)
18
+ end
19
+
20
+ private
21
+
22
+ def async_main_declared?(ast)
23
+ ast.declarations.any? do |decl|
24
+ decl.is_a?(AST::FunctionDef) && decl.name == "main" && decl.async
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "bindings/value_binding"
4
+ require_relative "bindings/function_binding"
5
+ require_relative "bindings/module_binding"
6
+ require_relative "bindings/attribute_binding"
7
+
8
+ module MilkTea
9
+ class FlowScope
10
+ def initialize = (@bindings = {})
11
+ def [](key) = @bindings[key]
12
+ def []=(key, val); @bindings[key] = val; end
13
+ def key?(key) = @bindings.key?(key)
14
+ def empty? = @bindings.empty?
15
+ def each(&block) = @bindings.each(&block)
16
+ def each_with_object(init, &block) = @bindings.each_with_object(init, &block)
17
+ end
18
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ AttributeBinding = Data.define(:name, :targets, :params, :module_name, :builtin, :ast)
5
+ BUILTIN_ATTRIBUTE_NAMES = %w[packed align deprecated test expect_fatal].freeze
6
+
7
+ module_function
8
+
9
+ def builtin_attribute_binding(name, types)
10
+ case name
11
+ when "packed"
12
+ AttributeBinding.new(
13
+ name: "packed",
14
+ targets: [:struct].freeze,
15
+ params: [].freeze,
16
+ module_name: nil,
17
+ builtin: true,
18
+ ast: nil,
19
+ )
20
+ when "align"
21
+ AttributeBinding.new(
22
+ name: "align",
23
+ targets: [:struct].freeze,
24
+ params: [Types::Registry.parameter("bytes", types.fetch("ptr_uint"))].freeze,
25
+ module_name: nil,
26
+ builtin: true,
27
+ ast: nil,
28
+ )
29
+ when "deprecated"
30
+ AttributeBinding.new(
31
+ name: "deprecated",
32
+ targets: %i[callable struct const enum flags union variant event].freeze,
33
+ params: [Types::Registry.parameter("message", types.fetch("str"))].freeze,
34
+ module_name: nil,
35
+ builtin: true,
36
+ ast: nil,
37
+ )
38
+ when "test"
39
+ AttributeBinding.new(
40
+ name: "test",
41
+ targets: [:callable].freeze,
42
+ params: [].freeze,
43
+ module_name: nil,
44
+ builtin: true,
45
+ ast: nil,
46
+ )
47
+ when "expect_fatal"
48
+ AttributeBinding.new(
49
+ name: "expect_fatal",
50
+ targets: [:callable].freeze,
51
+ params: [].freeze,
52
+ module_name: nil,
53
+ builtin: true,
54
+ ast: nil,
55
+ )
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ FunctionBinding = Data.define(:name, :type, :body_params, :body_return_type, :ast, :external, :async, :type_params, :type_param_constraints, :instances, :type_arguments, :owner, :specialization_owner, :type_substitutions, :declared_receiver_type)
5
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ ModuleBinding = Data.define(:name, :types, :type_declarations, :interfaces, :attributes, :attribute_applications, :values, :functions, :methods, :implemented_interfaces, :imports, :private_types, :private_interfaces, :private_attributes, :private_values, :private_functions, :private_methods, :private_implemented_interfaces) do
5
+ def private_type?(name)
6
+ private_types.key?(name)
7
+ end
8
+
9
+ def private_interface?(name)
10
+ private_interfaces.key?(name)
11
+ end
12
+
13
+ def private_attribute?(name)
14
+ private_attributes.key?(name)
15
+ end
16
+
17
+ def private_value?(name)
18
+ private_values.key?(name)
19
+ end
20
+
21
+ def private_function?(name)
22
+ private_functions.key?(name)
23
+ end
24
+
25
+ def private_method?(receiver_type, name)
26
+ return true if private_methods.fetch(receiver_type, {}).key?(name)
27
+
28
+ if receiver_type.is_a?(Types::GenericInstance)
29
+ dispatch_receiver_type = Types::Registry.generic_instance(
30
+ receiver_type.name,
31
+ receiver_type.arguments.each_with_index.map do |argument, index|
32
+ argument.is_a?(Types::LiteralTypeArg) ? argument : Types::TypeVar.new("__receiver_arg#{index}")
33
+ end,
34
+ )
35
+ return true if dispatch_receiver_type != receiver_type && private_methods.fetch(dispatch_receiver_type, {}).key?(name)
36
+ end
37
+
38
+ if receiver_type.is_a?(Types::Nullable)
39
+ dispatch_base_type = receiver_type.base
40
+ if dispatch_base_type.is_a?(Types::StructInstance)
41
+ dispatch_base_type = dispatch_base_type.definition
42
+ elsif dispatch_base_type.is_a?(Types::GenericInstance)
43
+ dispatch_base_type = Types::Registry.generic_instance(
44
+ dispatch_base_type.name,
45
+ dispatch_base_type.arguments.each_with_index.map do |argument, index|
46
+ argument.is_a?(Types::LiteralTypeArg) ? argument : Types::TypeVar.new("__receiver_arg#{index}")
47
+ end,
48
+ )
49
+ end
50
+
51
+ dispatch_receiver_type = Types::Registry.nullable(dispatch_base_type)
52
+ return true if dispatch_receiver_type != receiver_type && private_methods.fetch(dispatch_receiver_type, {}).key?(name)
53
+ end
54
+
55
+ receiver_type.is_a?(Types::StructInstance) && private_methods.fetch(receiver_type.definition, {}).key?(name)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ ValueBinding = Data.define(:id, :name, :storage_type, :flow_type, :mutable, :kind, :const_value) do
5
+ def type
6
+ flow_type || storage_type
7
+ end
8
+
9
+ def with_flow_type(refined_type)
10
+ ValueBinding.new(
11
+ id:,
12
+ name:,
13
+ storage_type:,
14
+ flow_type: refined_type == storage_type ? nil : refined_type,
15
+ mutable:,
16
+ kind:,
17
+ const_value:,
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ class CBackend
5
+ module AggregateUtils
6
+ private
7
+
8
+ def each_variant_arm_field_type
9
+ @program.variants.each do |variant_decl|
10
+ variant_decl.arms.each do |arm|
11
+ arm.fields.each do |field|
12
+ yield field.type
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ def sort_aggregate_decls(struct_decls, union_decls, variant_decls)
19
+ aggregate_decls = struct_decls + union_decls + variant_decls
20
+ by_c_name = aggregate_decls.each_with_object({}) do |aggregate_decl, declarations|
21
+ declarations[aggregate_decl.linkage_name] = aggregate_decl
22
+ end
23
+ variant_decls.each do |variant_decl|
24
+ variant_decl.arms.each do |arm|
25
+ next if arm.fields.empty?
26
+ by_c_name[arm.linkage_name] = variant_decl
27
+ end
28
+ end
29
+ visiting = {}
30
+ visited = {}
31
+ sorted = []
32
+
33
+ visit = lambda do |aggregate_decl|
34
+ return if visited[aggregate_decl.linkage_name]
35
+ raise CBackendError, "cyclic aggregate dependency involving #{aggregate_decl.linkage_name}" if visiting[aggregate_decl.linkage_name]
36
+
37
+ visiting[aggregate_decl.linkage_name] = true
38
+ aggregate_decl_dependencies(aggregate_decl).each do |dependency|
39
+ next unless by_c_name.key?(dependency)
40
+
41
+ visit.call(by_c_name.fetch(dependency))
42
+ end
43
+ visiting.delete(aggregate_decl.linkage_name)
44
+ visited[aggregate_decl.linkage_name] = true
45
+ sorted << aggregate_decl
46
+ end
47
+
48
+ aggregate_decls.each do |aggregate_decl|
49
+ visit.call(aggregate_decl)
50
+ end
51
+
52
+ sorted
53
+ end
54
+
55
+ def aggregate_decl_dependencies(aggregate_decl)
56
+ case aggregate_decl
57
+ when IR::StructDecl, IR::UnionDecl
58
+ aggregate_decl.fields.flat_map { |field| aggregate_type_dependencies(field.type) }.uniq
59
+ when IR::VariantDecl
60
+ own_name = aggregate_decl.linkage_name
61
+ aggregate_decl.arms.flat_map { |arm| arm.fields.flat_map { |field| aggregate_type_dependencies(field.type) } }
62
+ .uniq
63
+ .reject { |dep| dep == own_name }
64
+ else
65
+ []
66
+ end
67
+ end
68
+
69
+ def aggregate_type_dependencies(type)
70
+ case type
71
+ when Types::Nullable
72
+ if c_backend_pointer_like_type?(type.base)
73
+ aggregate_type_dependencies(type.base)
74
+ else
75
+ [nullable_opt_type_name(type)]
76
+ end
77
+ when Types::Task
78
+ [task_type_name(type)]
79
+ when Types::Proc
80
+ [proc_type_name(type)]
81
+ when Types::GenericInstance
82
+ if pointer_type?(type)
83
+ []
84
+ elsif array_type?(type)
85
+ aggregate_type_dependencies(array_element_type(type))
86
+ elsif str_buffer_type?(type)
87
+ [str_buffer_type_name(type)]
88
+ else
89
+ []
90
+ end
91
+ when Types::Function
92
+ []
93
+ when Types::Struct, Types::StructInstance, Types::Union, Types::Variant, Types::VariantInstance, Types::Event, Types::Subscription
94
+ [named_type_c_name(type)]
95
+ when Types::VariantArmPayload
96
+ [named_type_c_name(type), named_type_c_name(type.variant_type)]
97
+ else
98
+ []
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end