mt-lang 0.3.8 → 0.3.10

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 (200) hide show
  1. checksums.yaml +4 -4
  2. data/lib/milk_tea/base.rb +1 -2
  3. data/lib/milk_tea/bindings/bindgen/ast_parser.rb +0 -2
  4. data/lib/milk_tea/bindings/bindgen/declaration.rb +0 -2
  5. data/lib/milk_tea/bindings/bindgen/emitter.rb +0 -2
  6. data/lib/milk_tea/bindings/bindgen/overrides.rb +0 -2
  7. data/lib/milk_tea/bindings/bindgen/type_mapper.rb +51 -53
  8. data/lib/milk_tea/bindings/imported_bindings/generator.rb +7 -9
  9. data/lib/milk_tea/bindings/imported_bindings/method_source.rb +0 -2
  10. data/lib/milk_tea/bindings/imported_bindings/naming.rb +6 -8
  11. data/lib/milk_tea/bindings/imported_bindings.rb +0 -2
  12. data/lib/milk_tea/bindings/opengl_registry.rb +3 -7
  13. data/lib/milk_tea/bindings/steamworks.rb +12 -16
  14. data/lib/milk_tea/bindings/upstream_sources.rb +10 -14
  15. data/lib/milk_tea/bindings/vendored_box2d.rb +10 -12
  16. data/lib/milk_tea/bindings/vendored_cjson.rb +6 -8
  17. data/lib/milk_tea/bindings/vendored_flecs.rb +10 -12
  18. data/lib/milk_tea/bindings/vendored_glfw.rb +11 -13
  19. data/lib/milk_tea/bindings/vendored_libuv.rb +11 -13
  20. data/lib/milk_tea/bindings/vendored_pcre2.rb +11 -13
  21. data/lib/milk_tea/bindings/vendored_raylib.rb +6 -10
  22. data/lib/milk_tea/bindings/vendored_sdl3.rb +11 -13
  23. data/lib/milk_tea/bindings/vendored_steamworks.rb +1 -5
  24. data/lib/milk_tea/core/ast.rb +103 -45
  25. data/lib/milk_tea/core/async_runtime_installer.rb +0 -2
  26. data/lib/milk_tea/core/bindings/attribute_binding.rb +1 -3
  27. data/lib/milk_tea/core/c_backend/aggregate_utils.rb +147 -84
  28. data/lib/milk_tea/core/c_backend/control_flow_emission.rb +394 -396
  29. data/lib/milk_tea/core/c_backend/expressions.rb +489 -476
  30. data/lib/milk_tea/core/c_backend/feature_detection.rb +446 -437
  31. data/lib/milk_tea/core/c_backend/format_helpers.rb +0 -2
  32. data/lib/milk_tea/core/c_backend/reachability.rb +339 -341
  33. data/lib/milk_tea/core/c_backend/reinterpret.rb +231 -217
  34. data/lib/milk_tea/core/c_backend/runtime_helpers.rb +531 -526
  35. data/lib/milk_tea/core/c_backend/statements.rb +528 -530
  36. data/lib/milk_tea/core/c_backend/type_collectors.rb +1344 -1346
  37. data/lib/milk_tea/core/c_backend/type_declaration.rb +215 -213
  38. data/lib/milk_tea/core/c_backend/type_system.rb +347 -349
  39. data/lib/milk_tea/core/c_backend.rb +17 -9
  40. data/lib/milk_tea/core/compatibility_helpers.rb +0 -2
  41. data/lib/milk_tea/core/compile_time/const_eval.rb +7 -12
  42. data/lib/milk_tea/core/compile_time.rb +32 -38
  43. data/lib/milk_tea/core/control_flow/builder.rb +3 -5
  44. data/lib/milk_tea/core/control_flow/constant_propagation.rb +14 -17
  45. data/lib/milk_tea/core/control_flow/definite_assignment.rb +0 -1
  46. data/lib/milk_tea/core/ir.rb +10 -10
  47. data/lib/milk_tea/core/lexer/character_classes.rb +5 -7
  48. data/lib/milk_tea/core/lexer/format_strings.rb +7 -9
  49. data/lib/milk_tea/core/lexer/heredocs.rb +22 -22
  50. data/lib/milk_tea/core/lexer/indentation.rb +0 -2
  51. data/lib/milk_tea/core/lexer/numbers.rb +0 -2
  52. data/lib/milk_tea/core/lexer/recovery.rb +0 -2
  53. data/lib/milk_tea/core/lexer/strings.rb +0 -2
  54. data/lib/milk_tea/core/lexer/symbols.rb +0 -2
  55. data/lib/milk_tea/core/lexer/trivia.rb +0 -2
  56. data/lib/milk_tea/core/lexer.rb +0 -2
  57. data/lib/milk_tea/core/lowering/async/analysis.rb +0 -2
  58. data/lib/milk_tea/core/lowering/async/lowering.rb +1264 -1265
  59. data/lib/milk_tea/core/lowering/async/normalization.rb +0 -2
  60. data/lib/milk_tea/core/lowering/async.rb +627 -630
  61. data/lib/milk_tea/core/lowering/block.rb +413 -416
  62. data/lib/milk_tea/core/lowering/calls.rb +1381 -1384
  63. data/lib/milk_tea/core/lowering/declarations.rb +180 -183
  64. data/lib/milk_tea/core/lowering/dyn.rb +48 -50
  65. data/lib/milk_tea/core/lowering/events.rb +983 -985
  66. data/lib/milk_tea/core/lowering/expressions.rb +1513 -1518
  67. data/lib/milk_tea/core/lowering/foreign_cstr.rb +181 -184
  68. data/lib/milk_tea/core/lowering/functions.rb +185 -188
  69. data/lib/milk_tea/core/lowering/loops.rb +1028 -1031
  70. data/lib/milk_tea/core/lowering/proc.rb +363 -366
  71. data/lib/milk_tea/core/lowering/resolve.rb +2133 -2135
  72. data/lib/milk_tea/core/lowering/scans.rb +179 -181
  73. data/lib/milk_tea/core/lowering/str_buffer.rb +102 -105
  74. data/lib/milk_tea/core/lowering/utils.rb +1040 -1044
  75. data/lib/milk_tea/core/lowering.rb +5 -7
  76. data/lib/milk_tea/core/module_binder.rb +0 -2
  77. data/lib/milk_tea/core/module_loader/errors.rb +4 -2
  78. data/lib/milk_tea/core/module_loader.rb +113 -20
  79. data/lib/milk_tea/core/module_path_resolver.rb +0 -2
  80. data/lib/milk_tea/core/module_roots.rb +6 -8
  81. data/lib/milk_tea/core/parser/attributes.rb +0 -2
  82. data/lib/milk_tea/core/parser/blocks.rb +0 -2
  83. data/lib/milk_tea/core/parser/declarations.rb +0 -2
  84. data/lib/milk_tea/core/parser/expressions.rb +31 -14
  85. data/lib/milk_tea/core/parser/recovery.rb +0 -2
  86. data/lib/milk_tea/core/parser/statements.rb +0 -2
  87. data/lib/milk_tea/core/parser/types.rb +8 -10
  88. data/lib/milk_tea/core/parser.rb +1 -3
  89. data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +31 -33
  90. data/lib/milk_tea/core/pretty_printer/base_formatter.rb +0 -2
  91. data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +0 -2
  92. data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +0 -2
  93. data/lib/milk_tea/core/semantic_analyzer/attributes.rb +14 -16
  94. data/lib/milk_tea/core/semantic_analyzer/calls.rb +0 -2
  95. data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1 -14
  96. data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +18 -21
  97. data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +0 -3
  98. data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +12 -15
  99. data/lib/milk_tea/core/semantic_analyzer/generics.rb +57 -59
  100. data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +0 -2
  101. data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +5 -9
  102. data/lib/milk_tea/core/semantic_analyzer/nullability.rb +0 -3
  103. data/lib/milk_tea/core/semantic_analyzer/statements.rb +35 -40
  104. data/lib/milk_tea/core/semantic_analyzer/top_level.rb +10 -12
  105. data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +0 -6
  106. data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +102 -105
  107. data/lib/milk_tea/core/semantic_analyzer.rb +17 -8
  108. data/lib/milk_tea/core/types/layout.rb +21 -22
  109. data/lib/milk_tea/core/types/predicates.rb +0 -2
  110. data/lib/milk_tea/core/types/registry.rb +16 -18
  111. data/lib/milk_tea/core/types/visitor.rb +0 -4
  112. data/lib/milk_tea/dap/backends/lldb_dap.rb +0 -2
  113. data/lib/milk_tea/dap/protocol.rb +1 -1
  114. data/lib/milk_tea/dap/server/breakpoints.rb +0 -2
  115. data/lib/milk_tea/dap/server/debug_map.rb +0 -2
  116. data/lib/milk_tea/dap/server/handlers.rb +0 -2
  117. data/lib/milk_tea/dap/server/launch.rb +0 -2
  118. data/lib/milk_tea/dap/server/lldb_backend.rb +8 -10
  119. data/lib/milk_tea/dap/server/pause_diagnostics.rb +14 -16
  120. data/lib/milk_tea/dap/server/utilities.rb +0 -2
  121. data/lib/milk_tea/dap/server/wire.rb +0 -2
  122. data/lib/milk_tea/dap/server.rb +0 -2
  123. data/lib/milk_tea/lsp/diagnostics.rb +16 -16
  124. data/lib/milk_tea/lsp/server/call_hierarchy.rb +11 -12
  125. data/lib/milk_tea/lsp/server/code_actions.rb +355 -357
  126. data/lib/milk_tea/lsp/server/code_lens.rb +23 -25
  127. data/lib/milk_tea/lsp/server/completion.rb +873 -875
  128. data/lib/milk_tea/lsp/server/configuration.rb +129 -131
  129. data/lib/milk_tea/lsp/server/debug_info.rb +0 -2
  130. data/lib/milk_tea/lsp/server/definition.rb +564 -565
  131. data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +191 -193
  132. data/lib/milk_tea/lsp/server/execute_command.rb +0 -2
  133. data/lib/milk_tea/lsp/server/folding_range.rb +0 -4
  134. data/lib/milk_tea/lsp/server/formatting.rb +478 -480
  135. data/lib/milk_tea/lsp/server/hover.rb +1282 -1284
  136. data/lib/milk_tea/lsp/server/inlay_hints.rb +179 -181
  137. data/lib/milk_tea/lsp/server/lifecycle.rb +192 -194
  138. data/lib/milk_tea/lsp/server/linked_editing_range.rb +0 -2
  139. data/lib/milk_tea/lsp/server/on_type_formatting.rb +0 -2
  140. data/lib/milk_tea/lsp/server/progress.rb +0 -2
  141. data/lib/milk_tea/lsp/server/references.rb +316 -318
  142. data/lib/milk_tea/lsp/server/rename.rb +445 -447
  143. data/lib/milk_tea/lsp/server/selection_range.rb +0 -4
  144. data/lib/milk_tea/lsp/server/semantic_tokens.rb +1318 -1320
  145. data/lib/milk_tea/lsp/server/signature_help.rb +146 -148
  146. data/lib/milk_tea/lsp/server/text_documents.rb +99 -101
  147. data/lib/milk_tea/lsp/server/type_hierarchy.rb +2 -4
  148. data/lib/milk_tea/lsp/server/utilities.rb +397 -399
  149. data/lib/milk_tea/lsp/server.rb +0 -3
  150. data/lib/milk_tea/lsp/workspace/analysis.rb +40 -42
  151. data/lib/milk_tea/lsp/workspace/dependency_graph.rb +4 -10
  152. data/lib/milk_tea/lsp/workspace/utilities.rb +19 -19
  153. data/lib/milk_tea/packages/atomic_write.rb +4 -5
  154. data/lib/milk_tea/packages/dependency_solver.rb +15 -15
  155. data/lib/milk_tea/packages/lock.rb +4 -4
  156. data/lib/milk_tea/packages/manager_cli.rb +1 -1
  157. data/lib/milk_tea/packages/manifest.rb +3 -3
  158. data/lib/milk_tea/packages/registry_store.rb +4 -6
  159. data/lib/milk_tea/packages/services.rb +16 -16
  160. data/lib/milk_tea/packages/source_cache.rb +4 -6
  161. data/lib/milk_tea/packages/source_resolver.rb +44 -44
  162. data/lib/milk_tea/packages/version.rb +8 -8
  163. data/lib/milk_tea/tooling/build.rb +3 -7
  164. data/lib/milk_tea/tooling/build_cache.rb +0 -2
  165. data/lib/milk_tea/tooling/debug_info_formatter.rb +31 -33
  166. data/lib/milk_tea/tooling/debug_map.rb +8 -10
  167. data/lib/milk_tea/tooling/docs_app.rb +0 -2
  168. data/lib/milk_tea/tooling/linter/doc_tags.rb +25 -27
  169. data/lib/milk_tea/tooling/linter/fix_engine.rb +87 -24
  170. data/lib/milk_tea/tooling/linter/flow_rules.rb +44 -46
  171. data/lib/milk_tea/tooling/linter/imports_platform.rb +14 -16
  172. data/lib/milk_tea/tooling/linter/release_rules.rb +3 -5
  173. data/lib/milk_tea/tooling/linter/reserved_names.rb +23 -25
  174. data/lib/milk_tea/tooling/linter/rules.rb +87 -89
  175. data/lib/milk_tea/tooling/linter/source_helpers.rb +40 -42
  176. data/lib/milk_tea/tooling/linter/trailing_comma.rb +17 -19
  177. data/lib/milk_tea/tooling/linter/visitors.rb +162 -50
  178. data/lib/milk_tea/tooling/linter.rb +0 -2
  179. data/lib/milk_tea/tooling/project_scaffold.rb +0 -2
  180. data/lib/milk_tea/tooling/run.rb +0 -2
  181. data/lib/milk_tea/tooling/toolchain_cli.rb +0 -2
  182. data/std/cli.mt +13 -32
  183. data/std/color.mt +28 -28
  184. data/std/encoding.mt +4 -4
  185. data/std/graph.mt +1 -2
  186. data/std/hash.mt +14 -14
  187. data/std/http/server.mt +3 -3
  188. data/std/input.mt +1 -1
  189. data/std/json.mt +1 -1
  190. data/std/linear_algebra.mt +6 -6
  191. data/std/net/mux.mt +1 -1
  192. data/std/noise.mt +23 -23
  193. data/std/parse.mt +2 -2
  194. data/std/process.mt +3 -4
  195. data/std/sparse_set.mt +1 -1
  196. data/std/steering.mt +5 -5
  197. data/std/str.mt +1 -1
  198. data/std/tween.mt +4 -4
  199. data/std/utility.mt +3 -3
  200. metadata +2 -2
@@ -2,225 +2,222 @@
2
2
 
3
3
  module MilkTea
4
4
  module LowererDeclarations
5
- private
6
-
7
- def expanded_declarations
8
- @ctx.ast.declarations.flat_map do |decl|
9
- case decl
10
- when AST::WhenStmt
11
- val = compile_time_const_value(decl.discriminant)
12
- next [decl] if val.nil?
13
-
14
- chosen = decl.branches.find { |b| val == compile_time_const_value(b.pattern) }
15
- body = chosen ? chosen.body : (decl.else_body || [])
16
- body
17
- else
18
- [decl]
19
- end
5
+ def expanded_declarations
6
+ @ctx.ast.declarations.flat_map do |decl|
7
+ case decl
8
+ when AST::WhenStmt
9
+ val = compile_time_const_value(decl.discriminant)
10
+ next [decl] if val.nil?
11
+
12
+ chosen = decl.branches.find { |b| val == compile_time_const_value(b.pattern) }
13
+ body = chosen ? chosen.body : (decl.else_body || [])
14
+ body
15
+ else
16
+ [decl]
20
17
  end
21
18
  end
19
+ end
22
20
 
23
- def lower_constants
24
- expanded_declarations.grep(AST::ConstDecl).filter_map do |decl|
25
- type = @ctx.values.fetch(decl.name).type
26
- const_value = @ctx.values.fetch(decl.name).const_value
21
+ def lower_constants
22
+ expanded_declarations.grep(AST::ConstDecl).filter_map do |decl|
23
+ type = @ctx.values.fetch(decl.name).type
24
+ const_value = @ctx.values.fetch(decl.name).const_value
27
25
 
28
- next if type == Types::BUILTIN_TYPE_META_TYPE
26
+ next if type == Types::BUILTIN_TYPE_META_TYPE
29
27
 
30
- if const_value && (decl.value.is_a?(AST::Call) || decl.value.is_a?(AST::Specialization))
31
- value = lower_const_value_literal(type, const_value)
32
- elsif const_value && (decl.block_body || decl.value.is_a?(AST::ExpressionList))
33
- if const_value.is_a?(Array) && const_value.empty? && decl.value.is_a?(AST::ExpressionList) && !decl.value.elements.empty?
34
- value = lower_static_storage_initializer(decl.value, env: empty_env, expected_type: type)
35
- else
36
- value = lower_const_value_literal(type, const_value)
37
- end
38
- elsif decl.block_body || decl.value.is_a?(AST::ExpressionList)
39
- raise LoweringError.new("constant #{decl.name} has no compile-time value", line: decl.line, column: decl.column)
40
- else
28
+ if const_value && (decl.value.is_a?(AST::Call) || decl.value.is_a?(AST::Specialization))
29
+ value = lower_const_value_literal(type, const_value)
30
+ elsif const_value && (decl.block_body || decl.value.is_a?(AST::ExpressionList))
31
+ if const_value.is_a?(Array) && const_value.empty? && decl.value.is_a?(AST::ExpressionList) && !decl.value.elements.empty?
41
32
  value = lower_static_storage_initializer(decl.value, env: empty_env, expected_type: type)
33
+ else
34
+ value = lower_const_value_literal(type, const_value)
42
35
  end
43
-
44
- IR::Constant.new(name: decl.name, linkage_name: value_c_name(decl.name), type:, value:,
45
- line: decl.line, source_path: @ctx.current_analysis_path)
36
+ elsif decl.block_body || decl.value.is_a?(AST::ExpressionList)
37
+ raise LoweringError.new("constant #{decl.name} has no compile-time value", line: decl.line, column: decl.column)
38
+ else
39
+ value = lower_static_storage_initializer(decl.value, env: empty_env, expected_type: type)
46
40
  end
47
- end
48
41
 
49
- def lower_const_value_literal(type, const_value)
50
- case const_value
51
- when Integer
52
- value = if type.respond_to?(:integer_width) && (width = type.integer_width) && width < 64
53
- mask = (1 << width) - 1
54
- masked = const_value & mask
55
- if type.respond_to?(:unsigned_integer?) && !type.unsigned_integer? && masked >= (1 << (width - 1))
56
- masked - (1 << width)
57
- else
58
- masked
59
- end
60
- else
61
- const_value
62
- end
63
- IR::IntegerLiteral.new(value:, type:)
64
- when Float
65
- IR::FloatLiteral.new(value: const_value, type:)
66
- when String
67
- IR::StringLiteral.new(value: const_value, type:, cstring: false)
68
- when TrueClass, FalseClass
69
- IR::BooleanLiteral.new(value: const_value, type:)
70
- when Array
71
- element_type = type.respond_to?(:arguments) ? type.arguments.first : @ctx.types["int"]
72
- elements = const_value.map do |element|
73
- lower_const_value_literal(element_type, element)
74
- end
75
- IR::ArrayLiteral.new(type:, elements:)
76
- when Hash
77
- fields = const_value.map do |name, field_value|
78
- field_type = type.field(name)
79
- raise LoweringError.new("constant struct field #{name} not found in #{type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless field_type
80
- IR::AggregateField.new(name:, value: lower_const_value_literal(field_type, field_value))
42
+ IR::Constant.new(name: decl.name, linkage_name: value_c_name(decl.name), type:, value:, line: decl.line, path: @ctx.current_analysis_path)
43
+ end
44
+ end
45
+
46
+ def lower_const_value_literal(type, const_value)
47
+ case const_value
48
+ when Integer
49
+ value = if type.respond_to?(:integer_width) && (width = type.integer_width) && width < 64
50
+ mask = (1 << width) - 1
51
+ masked = const_value & mask
52
+ if type.respond_to?(:unsigned_integer?) && !type.unsigned_integer? && masked >= (1 << (width - 1))
53
+ masked - (1 << width)
54
+ else
55
+ masked
81
56
  end
82
- IR::AggregateLiteral.new(type:, fields:)
83
57
  else
84
- IR::IntegerLiteral.new(value: 0, type:)
58
+ const_value
85
59
  end
86
- end
87
-
88
- def lower_globals
89
- expanded_declarations.filter_map do |decl|
90
- next unless decl.is_a?(AST::VarDecl) || decl.is_a?(AST::EventDecl)
91
-
92
- type = @ctx.values.fetch(decl.name).type
93
- ensure_event_runtime(type) if type.is_a?(Types::Event)
94
- value = if decl.is_a?(AST::VarDecl) && decl.value
95
- lower_static_storage_initializer(decl.value, env: empty_env, expected_type: type)
96
- else
97
- IR::ZeroInit.new(type: type)
98
- end
99
- IR::Global.new(name: decl.name, linkage_name: value_c_name(decl.name), type:, value:)
60
+ IR::IntegerLiteral.new(value:, type:)
61
+ when Float
62
+ IR::FloatLiteral.new(value: const_value, type:)
63
+ when String
64
+ IR::StringLiteral.new(value: const_value, type:, cstring: false)
65
+ when TrueClass, FalseClass
66
+ IR::BooleanLiteral.new(value: const_value, type:)
67
+ when Array
68
+ element_type = type.respond_to?(:arguments) ? type.arguments.first : @ctx.types["int"]
69
+ elements = const_value.map do |element|
70
+ lower_const_value_literal(element_type, element)
100
71
  end
101
- end
102
-
103
- def lower_opaques
104
- expanded_declarations.grep(AST::OpaqueDecl).map do |decl|
105
- opaque_type = @ctx.opaque_types.fetch(decl.name)
106
- IR::OpaqueDecl.new(
107
- name: decl.name,
108
- linkage_name: opaque_c_type_name(opaque_type),
109
- forward_declarable: opaque_forward_declarable?(opaque_type),
110
- source_module: @ctx.module_name,
111
- )
72
+ IR::ArrayLiteral.new(type:, elements:)
73
+ when Hash
74
+ fields = const_value.map do |name, field_value|
75
+ field_type = type.field(name)
76
+ raise LoweringError.new("constant struct field #{name} not found in #{type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless field_type
77
+ IR::AggregateField.new(name:, value: lower_const_value_literal(field_type, field_value))
112
78
  end
79
+ IR::AggregateLiteral.new(type:, fields:)
80
+ else
81
+ IR::IntegerLiteral.new(value: 0, type:)
113
82
  end
83
+ end
114
84
 
115
- def lower_imported_external_opaques
116
- each_raw_module_analysis.flat_map do |analysis|
117
- analysis.ast.declarations.grep(AST::OpaqueDecl).filter_map do |decl|
118
- opaque_type = analysis.types.fetch(decl.name)
119
- next unless forward_declarable_external_opaque?(opaque_type)
120
-
121
- IR::OpaqueDecl.new(name: decl.name, linkage_name: opaque_c_type_name(opaque_type), forward_declarable: true, source_module: analysis.module_name)
122
- end
123
- end.uniq { |decl| decl.linkage_name }
124
- end
85
+ def lower_globals
86
+ expanded_declarations.filter_map do |decl|
87
+ next unless decl.is_a?(AST::VarDecl) || decl.is_a?(AST::EventDecl)
125
88
 
126
- def lower_static_asserts
127
- expanded_declarations.grep(AST::StaticAssert).map do |statement|
128
- lower_static_assert(statement, env: empty_env)
89
+ type = @ctx.values.fetch(decl.name).type
90
+ ensure_event_runtime(type) if type.is_a?(Types::Event)
91
+ value = if decl.is_a?(AST::VarDecl) && decl.value
92
+ lower_static_storage_initializer(decl.value, env: empty_env, expected_type: type)
93
+ else
94
+ IR::ZeroInit.new(type: type)
129
95
  end
96
+ IR::Global.new(name: decl.name, linkage_name: value_c_name(decl.name), type:, value:)
130
97
  end
131
-
132
- def lower_static_assert(statement, env:)
133
- condition_value = compile_time_const_value(statement.condition, env:)
134
- raise LoweringError.new("static_assert condition must lower to a compile-time bool constant", line: 0, column: 0, path: @ctx.current_analysis_path) unless condition_value == true || condition_value == false
135
-
136
- IR::StaticAssert.new(
137
- condition: IR::BooleanLiteral.new(value: condition_value, type: @ctx.types.fetch("bool")),
138
- message: lower_expression(statement.message, env:, expected_type: @ctx.types.fetch("str")),
98
+ end
99
+
100
+ def lower_opaques
101
+ expanded_declarations.grep(AST::OpaqueDecl).map do |decl|
102
+ opaque_type = @ctx.opaque_types.fetch(decl.name)
103
+ IR::OpaqueDecl.new(
104
+ name: decl.name,
105
+ linkage_name: opaque_c_type_name(opaque_type),
106
+ forward_declarable: opaque_forward_declarable?(opaque_type),
107
+ source_module: @ctx.module_name,
139
108
  )
140
109
  end
110
+ end
141
111
 
142
- def lower_structs
143
- expanded_declarations.grep(AST::StructDecl).filter_map do |decl|
144
- next unless decl.type_params.empty?
145
-
146
- results = []
147
- lower_one_struct(decl, decl.name, results)
148
- results
149
- end.flatten
150
- end
112
+ def lower_imported_external_opaques
113
+ each_raw_module_analysis.flat_map do |analysis|
114
+ analysis.ast.declarations.grep(AST::OpaqueDecl).filter_map do |decl|
115
+ opaque_type = analysis.types.fetch(decl.name)
116
+ next unless forward_declarable_external_opaque?(opaque_type)
151
117
 
152
- def lower_one_struct(decl, qualified_name, results)
153
- struct_type = @ctx.struct_types.fetch(qualified_name)
154
- fields = decl.fields.map do |field|
155
- IR::Field.new(name: field.name, type: struct_type.field(field.name))
156
- end
157
- decl.events.each do |event_decl|
158
- event_type = struct_type.event(event_decl.name)
159
- ensure_event_runtime(event_type)
160
- fields << IR::Field.new(name: event_type.hidden_field_name, type: event_type)
118
+ IR::OpaqueDecl.new(name: decl.name, linkage_name: opaque_c_type_name(opaque_type), forward_declarable: true, source_module: analysis.module_name)
161
119
  end
120
+ end.uniq { |decl| decl.linkage_name }
121
+ end
162
122
 
163
- results << IR::StructDecl.new(name: decl.name, linkage_name: c_type_name(struct_type), fields:, packed: decl.packed, alignment: decl.alignment, source_module: @ctx.module_name)
123
+ def lower_static_asserts
124
+ expanded_declarations.grep(AST::StaticAssert).map do |statement|
125
+ lower_static_assert(statement, env: empty_env)
126
+ end
127
+ end
128
+
129
+ def lower_static_assert(statement, env:)
130
+ condition_value = compile_time_const_value(statement.condition, env:)
131
+ raise LoweringError.new("static_assert condition must lower to a compile-time bool constant", line: 0, column: 0, path: @ctx.current_analysis_path) unless condition_value == true || condition_value == false
132
+
133
+ IR::StaticAssert.new(
134
+ condition: IR::BooleanLiteral.new(value: condition_value, type: @ctx.types.fetch("bool")),
135
+ message: lower_expression(statement.message, env:, expected_type: @ctx.types.fetch("str")),
136
+ )
137
+ end
138
+
139
+ def lower_structs
140
+ expanded_declarations.grep(AST::StructDecl).filter_map do |decl|
141
+ next unless decl.type_params.empty?
142
+
143
+ results = []
144
+ lower_one_struct(decl, decl.name, results)
145
+ results
146
+ end.flatten
147
+ end
148
+
149
+ def lower_one_struct(decl, qualified_name, results)
150
+ struct_type = @ctx.struct_types.fetch(qualified_name)
151
+ fields = decl.fields.map do |field|
152
+ IR::Field.new(name: field.name, type: struct_type.field(field.name))
153
+ end
154
+ decl.events.each do |event_decl|
155
+ event_type = struct_type.event(event_decl.name)
156
+ ensure_event_runtime(event_type)
157
+ fields << IR::Field.new(name: event_type.hidden_field_name, type: event_type)
158
+ end
164
159
 
165
- decl.nested_types.each do |nested|
166
- lower_one_struct(nested, "#{qualified_name}.#{nested.name}", results)
167
- end
160
+ results << IR::StructDecl.new(name: decl.name, linkage_name: c_type_name(struct_type), fields:, packed: decl.packed, alignment: decl.alignment, source_module: @ctx.module_name)
161
+
162
+ decl.nested_types.each do |nested|
163
+ lower_one_struct(nested, "#{qualified_name}.#{nested.name}", results)
168
164
  end
165
+ end
169
166
 
170
- def lower_unions
171
- expanded_declarations.grep(AST::UnionDecl).map do |decl|
172
- union_type = @ctx.union_types.fetch(decl.name)
173
- fields = decl.fields.map do |field|
174
- IR::Field.new(name: field.name, type: union_type.field(field.name))
175
- end
176
- IR::UnionDecl.new(name: decl.name, linkage_name: c_type_name(union_type), fields:, source_module: @ctx.module_name)
167
+ def lower_unions
168
+ expanded_declarations.grep(AST::UnionDecl).map do |decl|
169
+ union_type = @ctx.union_types.fetch(decl.name)
170
+ fields = decl.fields.map do |field|
171
+ IR::Field.new(name: field.name, type: union_type.field(field.name))
177
172
  end
173
+ IR::UnionDecl.new(name: decl.name, linkage_name: c_type_name(union_type), fields:, source_module: @ctx.module_name)
178
174
  end
179
-
180
- def lower_enums
181
- expanded_declarations.filter_map do |decl|
182
- case decl
183
- when AST::EnumDecl, AST::FlagsDecl
184
- enum_type = @ctx.types.fetch(decl.name)
185
- backing_type = enum_type.backing_type
186
- members = decl.members.map do |member|
187
- value = if member.value
188
- lower_expression(member.value, env: empty_env, expected_type: backing_type)
189
- else
190
- IR::IntegerLiteral.new(value: enum_type.member_value(member.name), type: backing_type)
191
- end
192
- IR::EnumMember.new(name: member.name, linkage_name: enum_member_c_name(enum_type, member.name), value:)
193
- end
194
-
195
- IR::EnumDecl.new(
196
- name: decl.name,
197
- linkage_name: c_type_name(enum_type),
198
- backing_type:,
199
- members:,
200
- flags: decl.is_a?(AST::FlagsDecl),
201
- )
175
+ end
176
+
177
+ def lower_enums
178
+ expanded_declarations.filter_map do |decl|
179
+ case decl
180
+ when AST::EnumDecl, AST::FlagsDecl
181
+ enum_type = @ctx.types.fetch(decl.name)
182
+ backing_type = enum_type.backing_type
183
+ members = decl.members.map do |member|
184
+ value = if member.value
185
+ lower_expression(member.value, env: empty_env, expected_type: backing_type)
186
+ else
187
+ IR::IntegerLiteral.new(value: enum_type.member_value(member.name), type: backing_type)
188
+ end
189
+ IR::EnumMember.new(name: member.name, linkage_name: enum_member_c_name(enum_type, member.name), value:)
202
190
  end
191
+
192
+ IR::EnumDecl.new(
193
+ name: decl.name,
194
+ linkage_name: c_type_name(enum_type),
195
+ backing_type:,
196
+ members:,
197
+ flags: decl.is_a?(AST::FlagsDecl),
198
+ )
203
199
  end
204
200
  end
201
+ end
202
+
203
+ def lower_variants
204
+ expanded_declarations.filter_map do |decl|
205
+ next unless decl.is_a?(AST::VariantDecl)
206
+
207
+ variant_type = @ctx.types.fetch(decl.name)
208
+ next if variant_type.is_a?(Types::GenericVariantDefinition)
205
209
 
206
- def lower_variants
207
- expanded_declarations.filter_map do |decl|
208
- next unless decl.is_a?(AST::VariantDecl)
209
-
210
- variant_type = @ctx.types.fetch(decl.name)
211
- next if variant_type.is_a?(Types::GenericVariantDefinition)
212
-
213
- outer_c = c_type_name(variant_type)
214
- arms = decl.arms.map do |arm|
215
- arm_c = "#{outer_c}_#{arm.name}"
216
- fields = arm.fields.map do |field|
217
- field_type = variant_type.arm(arm.name).fetch(field.name)
218
- IR::Field.new(name: field.name, type: field_type)
219
- end
220
- IR::VariantArm.new(name: arm.name, linkage_name: arm_c, fields:)
210
+ outer_c = c_type_name(variant_type)
211
+ arms = decl.arms.map do |arm|
212
+ arm_c = "#{outer_c}_#{arm.name}"
213
+ fields = arm.fields.map do |field|
214
+ field_type = variant_type.arm(arm.name).fetch(field.name)
215
+ IR::Field.new(name: field.name, type: field_type)
221
216
  end
222
- IR::VariantDecl.new(name: decl.name, linkage_name: outer_c, arms:, source_module: @ctx.module_name)
217
+ IR::VariantArm.new(name: arm.name, linkage_name: arm_c, fields:)
223
218
  end
219
+ IR::VariantDecl.new(name: decl.name, linkage_name: outer_c, arms:, source_module: @ctx.module_name)
224
220
  end
221
+ end
225
222
  end
226
223
  end
@@ -2,8 +2,6 @@
2
2
 
3
3
  module MilkTea
4
4
  module LowererDyn
5
- private
6
-
7
5
  def lower_adapt_call(expression, env:, type:, interface:)
8
6
  argument = expression.arguments.fetch(0)
9
7
  arg_value = lower_expression(argument.value, env:)
@@ -126,54 +124,54 @@ module MilkTea
126
124
  ]
127
125
 
128
126
  body = if is_editable
129
- [
130
- IR::ReturnStmt.new(value: IR::Call.new(
131
- callee: real_c_name,
132
- arguments: [
133
- IR::Cast.new(target_type: ptr_to_concrete, expression: IR::Name.new(name: "data", type: void_ptr, pointer: false), type: ptr_to_concrete),
134
- *method_binding.params.map.with_index { |p, i| IR::Name.new(name: p.name || "arg#{i}", type: p.type, pointer: false) },
135
- ],
136
- type: method_binding.return_type,
137
- )),
138
- ]
139
- else
140
- if method_ast.kind == :static
141
- [
142
- IR::ReturnStmt.new(value: IR::Call.new(
143
- callee: real_c_name,
144
- arguments: method_binding.params.map.with_index { |p, i| IR::Name.new(name: p.name || "arg#{i}", type: p.type, pointer: false) },
145
- type: method_binding.return_type,
146
- )),
147
- ]
148
- elsif receiver_type_uses_pointer_lowering?(concrete_type)
149
- [
150
- IR::ReturnStmt.new(value: IR::Call.new(
151
- callee: real_c_name,
152
- arguments: [
153
- IR::Cast.new(target_type: ptr_to_concrete, expression: IR::Name.new(name: "data", type: void_ptr, pointer: false), type: ptr_to_concrete),
154
- *method_binding.params.map.with_index { |p, i| IR::Name.new(name: p.name || "arg#{i}", type: p.type, pointer: false) },
155
- ],
156
- type: method_binding.return_type,
157
- )),
158
- ]
159
- else
160
- # The receiver is always passed here; the C backend's
161
- # omitted-receiver call logic drops it when the target
162
- # method's unused receiver parameter was omitted (the same
163
- # single source of truth every ordinary method call uses,
164
- # which requires a String callee).
165
- [
166
- IR::ReturnStmt.new(value: IR::Call.new(
167
- callee: real_c_name,
168
- arguments: [
169
- IR::Unary.new(operator: "*", operand: IR::Cast.new(target_type: ptr_to_concrete, expression: IR::Name.new(name: "data", type: void_ptr, pointer: false), type: ptr_to_concrete), type: concrete_type),
170
- *method_binding.params.map.with_index { |p, i| IR::Name.new(name: p.name || "arg#{i}", type: p.type, pointer: false) },
171
- ],
172
- type: method_binding.return_type,
173
- )),
174
- ]
175
- end
176
- end
127
+ [
128
+ IR::ReturnStmt.new(value: IR::Call.new(
129
+ callee: real_c_name,
130
+ arguments: [
131
+ IR::Cast.new(target_type: ptr_to_concrete, expression: IR::Name.new(name: "data", type: void_ptr, pointer: false), type: ptr_to_concrete),
132
+ *method_binding.params.map.with_index { |p, i| IR::Name.new(name: p.name || "arg#{i}", type: p.type, pointer: false) },
133
+ ],
134
+ type: method_binding.return_type,
135
+ )),
136
+ ]
137
+ else
138
+ if method_ast.kind == :static
139
+ [
140
+ IR::ReturnStmt.new(value: IR::Call.new(
141
+ callee: real_c_name,
142
+ arguments: method_binding.params.map.with_index { |p, i| IR::Name.new(name: p.name || "arg#{i}", type: p.type, pointer: false) },
143
+ type: method_binding.return_type,
144
+ )),
145
+ ]
146
+ elsif receiver_type_uses_pointer_lowering?(concrete_type)
147
+ [
148
+ IR::ReturnStmt.new(value: IR::Call.new(
149
+ callee: real_c_name,
150
+ arguments: [
151
+ IR::Cast.new(target_type: ptr_to_concrete, expression: IR::Name.new(name: "data", type: void_ptr, pointer: false), type: ptr_to_concrete),
152
+ *method_binding.params.map.with_index { |p, i| IR::Name.new(name: p.name || "arg#{i}", type: p.type, pointer: false) },
153
+ ],
154
+ type: method_binding.return_type,
155
+ )),
156
+ ]
157
+ else
158
+ # The receiver is always passed here; the C backend's
159
+ # omitted-receiver call logic drops it when the target
160
+ # method's unused receiver parameter was omitted (the same
161
+ # single source of truth every ordinary method call uses,
162
+ # which requires a String callee).
163
+ [
164
+ IR::ReturnStmt.new(value: IR::Call.new(
165
+ callee: real_c_name,
166
+ arguments: [
167
+ IR::Unary.new(operator: "*", operand: IR::Cast.new(target_type: ptr_to_concrete, expression: IR::Name.new(name: "data", type: void_ptr, pointer: false), type: ptr_to_concrete), type: concrete_type),
168
+ *method_binding.params.map.with_index { |p, i| IR::Name.new(name: p.name || "arg#{i}", type: p.type, pointer: false) },
169
+ ],
170
+ type: method_binding.return_type,
171
+ )),
172
+ ]
173
+ end
174
+ end
177
175
 
178
176
  @artifacts.synthetic_functions << IR::Function.new(
179
177
  name: "__dyn_#{concrete_type_name}_#{method_name}",