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,205 +2,202 @@
2
2
 
3
3
  module MilkTea
4
4
  module LowererForeignCstr
5
- private
6
-
7
-
8
- def lower_foreign_cstr_list_argument_value(parameter, argument_value, env:, lowered:, cleanup:)
9
- if (direct_value = lower_direct_foreign_cstr_list_argument_value(parameter, argument_value, env:, lowered:))
10
- return direct_value
11
- end
12
-
13
- public_type = parameter.type
14
- boundary_type = parameter.boundary_type
15
- items_type = pointer_to(pointer_to(@ctx.types.fetch("char")))
16
- data_type = pointer_to(@ctx.types.fetch("char"))
17
- len_type = @ctx.types.fetch("ptr_uint")
18
- lowered_value = lower_contextual_expression(argument_value, env:, expected_type: public_type)
19
- items_name = fresh_c_temp_name(env, "foreign_cstr_items")
20
- data_name = fresh_c_temp_name(env, "foreign_cstr_data")
21
- len_name = fresh_c_temp_name(env, "foreign_cstr_len")
22
-
23
- lowered << IR::LocalDecl.new(
24
- name: items_name,
25
- linkage_name: items_name,
26
- type: items_type,
27
- value: IR::NullLiteral.new(type: items_type),
28
- )
29
- lowered << IR::LocalDecl.new(
30
- name: data_name,
31
- linkage_name: data_name,
32
- type: data_type,
33
- value: IR::NullLiteral.new(type: data_type),
34
- )
35
- lowered << IR::LocalDecl.new(
36
- name: len_name,
37
- linkage_name: len_name,
38
- type: len_type,
39
- value: IR::IntegerLiteral.new(value: 0, type: len_type),
40
- )
41
- lowered << IR::ExpressionStmt.new(
42
- expression: IR::Call.new(
43
- callee: "mt_foreign_strs_to_cstrs_temp",
44
- arguments: [
45
- lowered_value,
46
- IR::AddressOf.new(expression: IR::Name.new(name: items_name, type: items_type, pointer: false), type: pointer_to(items_type)),
47
- IR::AddressOf.new(expression: IR::Name.new(name: data_name, type: data_type, pointer: false), type: pointer_to(data_type)),
48
- IR::AddressOf.new(expression: IR::Name.new(name: len_name, type: len_type, pointer: false), type: pointer_to(len_type)),
49
- ],
50
- type: @ctx.types.fetch("void"),
51
- ),
52
- )
53
- cleanup << IR::ExpressionStmt.new(
54
- expression: IR::Call.new(
55
- callee: "mt_free_foreign_cstrs_temp",
56
- arguments: [
57
- IR::Name.new(name: items_name, type: items_type, pointer: false),
58
- IR::Name.new(name: data_name, type: data_type, pointer: false),
59
- ],
60
- type: @ctx.types.fetch("void"),
61
- ),
62
- )
63
-
64
- converted_data = foreign_identity_projection_expression(
65
- IR::Name.new(name: items_name, type: items_type, pointer: false),
66
- pointer_to(boundary_type.element_type),
67
- )
68
- raise LoweringError.new("unsupported foreign boundary mapping #{public_type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted_data
5
+ def lower_foreign_cstr_list_argument_value(parameter, argument_value, env:, lowered:, cleanup:)
6
+ if (direct_value = lower_direct_foreign_cstr_list_argument_value(parameter, argument_value, env:, lowered:))
7
+ return direct_value
8
+ end
69
9
 
70
- IR::AggregateLiteral.new(
10
+ public_type = parameter.type
11
+ boundary_type = parameter.boundary_type
12
+ items_type = pointer_to(pointer_to(@ctx.types.fetch("char")))
13
+ data_type = pointer_to(@ctx.types.fetch("char"))
14
+ len_type = @ctx.types.fetch("ptr_uint")
15
+ lowered_value = lower_contextual_expression(argument_value, env:, expected_type: public_type)
16
+ items_name = fresh_c_temp_name(env, "foreign_cstr_items")
17
+ data_name = fresh_c_temp_name(env, "foreign_cstr_data")
18
+ len_name = fresh_c_temp_name(env, "foreign_cstr_len")
19
+
20
+ lowered << IR::LocalDecl.new(
21
+ name: items_name,
22
+ linkage_name: items_name,
23
+ type: items_type,
24
+ value: IR::NullLiteral.new(type: items_type),
25
+ )
26
+ lowered << IR::LocalDecl.new(
27
+ name: data_name,
28
+ linkage_name: data_name,
29
+ type: data_type,
30
+ value: IR::NullLiteral.new(type: data_type),
31
+ )
32
+ lowered << IR::LocalDecl.new(
33
+ name: len_name,
34
+ linkage_name: len_name,
35
+ type: len_type,
36
+ value: IR::IntegerLiteral.new(value: 0, type: len_type),
37
+ )
38
+ lowered << IR::ExpressionStmt.new(
39
+ expression: IR::Call.new(
40
+ callee: "mt_foreign_strs_to_cstrs_temp",
41
+ arguments: [
42
+ lowered_value,
43
+ IR::AddressOf.new(expression: IR::Name.new(name: items_name, type: items_type, pointer: false), type: pointer_to(items_type)),
44
+ IR::AddressOf.new(expression: IR::Name.new(name: data_name, type: data_type, pointer: false), type: pointer_to(data_type)),
45
+ IR::AddressOf.new(expression: IR::Name.new(name: len_name, type: len_type, pointer: false), type: pointer_to(len_type)),
46
+ ],
47
+ type: @ctx.types.fetch("void"),
48
+ ),
49
+ )
50
+ cleanup << IR::ExpressionStmt.new(
51
+ expression: IR::Call.new(
52
+ callee: "mt_free_foreign_cstrs_temp",
53
+ arguments: [
54
+ IR::Name.new(name: items_name, type: items_type, pointer: false),
55
+ IR::Name.new(name: data_name, type: data_type, pointer: false),
56
+ ],
57
+ type: @ctx.types.fetch("void"),
58
+ ),
59
+ )
60
+
61
+ converted_data = foreign_identity_projection_expression(
62
+ IR::Name.new(name: items_name, type: items_type, pointer: false),
63
+ pointer_to(boundary_type.element_type),
64
+ )
65
+ raise LoweringError.new("unsupported foreign boundary mapping #{public_type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted_data
66
+
67
+ IR::AggregateLiteral.new(
68
+ type: boundary_type,
69
+ fields: [
70
+ IR::AggregateField.new(name: "data", value: converted_data),
71
+ IR::AggregateField.new(name: "len", value: IR::Name.new(name: len_name, type: len_type, pointer: false)),
72
+ ],
73
+ )
74
+ end
75
+
76
+ def lower_direct_foreign_cstr_list_argument_value(parameter, argument_value, env:, lowered:)
77
+ actual_type = infer_expression_type(argument_value, env:)
78
+ return unless array_type?(actual_type)
79
+ return unless cstr_list_backed_expression?(argument_value, env)
80
+
81
+ boundary_type = parameter.boundary_type
82
+ boundary_element_type = boundary_type.element_type
83
+ len = array_length(actual_type)
84
+ len_type = @ctx.types.fetch("ptr_uint")
85
+
86
+ if len.zero?
87
+ return IR::AggregateLiteral.new(
71
88
  type: boundary_type,
72
89
  fields: [
73
- IR::AggregateField.new(name: "data", value: converted_data),
74
- IR::AggregateField.new(name: "len", value: IR::Name.new(name: len_name, type: len_type, pointer: false)),
90
+ IR::AggregateField.new(name: "data", value: IR::NullLiteral.new(type: pointer_to(boundary_element_type))),
91
+ IR::AggregateField.new(name: "len", value: IR::IntegerLiteral.new(value: 0, type: len_type)),
75
92
  ],
76
93
  )
77
94
  end
78
95
 
79
- def lower_direct_foreign_cstr_list_argument_value(parameter, argument_value, env:, lowered:)
80
- actual_type = infer_expression_type(argument_value, env:)
81
- return unless array_type?(actual_type)
82
- return unless cstr_list_backed_expression?(argument_value, env)
83
-
84
- boundary_type = parameter.boundary_type
85
- boundary_element_type = boundary_type.element_type
86
- len = array_length(actual_type)
87
- len_type = @ctx.types.fetch("ptr_uint")
88
-
89
- if len.zero?
90
- return IR::AggregateLiteral.new(
91
- type: boundary_type,
92
- fields: [
93
- IR::AggregateField.new(name: "data", value: IR::NullLiteral.new(type: pointer_to(boundary_element_type))),
94
- IR::AggregateField.new(name: "len", value: IR::IntegerLiteral.new(value: 0, type: len_type)),
95
- ],
96
- )
97
- end
98
-
99
- source = lower_expression(argument_value, env:, expected_type: actual_type)
100
- item_type = array_element_type(actual_type)
101
- items_array_type = Types::Registry.generic_instance("array", [boundary_element_type, Types::LiteralTypeArg.new(len)])
102
- items_name = fresh_c_temp_name(env, "foreign_cstr_items")
103
- items = (0...len).map do |index|
104
- item = IR::Index.new(
105
- receiver: source,
106
- index: IR::IntegerLiteral.new(value: index, type: len_type),
107
- type: item_type,
108
- )
109
- item = IR::Member.new(receiver: item, member: "data", type: pointer_to(@ctx.types.fetch("char"))) if item_type == @ctx.types.fetch("str")
110
-
111
- converted = foreign_identity_projection_expression(item, boundary_element_type)
112
- raise LoweringError.new("unsupported foreign boundary mapping #{parameter.type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted
113
-
114
- converted
115
- end
116
-
117
- lowered << IR::LocalDecl.new(
118
- name: items_name,
119
- linkage_name: items_name,
120
- type: items_array_type,
121
- value: IR::ArrayLiteral.new(type: items_array_type, elements: items),
96
+ source = lower_expression(argument_value, env:, expected_type: actual_type)
97
+ item_type = array_element_type(actual_type)
98
+ items_array_type = Types::Registry.generic_instance("array", [boundary_element_type, Types::LiteralTypeArg.new(len)])
99
+ items_name = fresh_c_temp_name(env, "foreign_cstr_items")
100
+ items = (0...len).map do |index|
101
+ item = IR::Index.new(
102
+ receiver: source,
103
+ index: IR::IntegerLiteral.new(value: index, type: len_type),
104
+ type: item_type,
122
105
  )
106
+ item = IR::Member.new(receiver: item, member: "data", type: pointer_to(@ctx.types.fetch("char"))) if item_type == @ctx.types.fetch("str")
123
107
 
124
- items_ref = IR::Name.new(name: items_name, type: items_array_type, pointer: false)
125
- IR::AggregateLiteral.new(
126
- type: boundary_type,
127
- fields: [
128
- IR::AggregateField.new(
129
- name: "data",
130
- value: IR::AddressOf.new(
131
- expression: IR::Index.new(
132
- receiver: items_ref,
133
- index: IR::IntegerLiteral.new(value: 0, type: len_type),
134
- type: boundary_element_type,
135
- ),
136
- type: pointer_to(boundary_element_type),
137
- ),
138
- ),
139
- IR::AggregateField.new(name: "len", value: IR::IntegerLiteral.new(value: len, type: len_type)),
140
- ],
141
- )
142
- end
108
+ converted = foreign_identity_projection_expression(item, boundary_element_type)
109
+ raise LoweringError.new("unsupported foreign boundary mapping #{parameter.type} as #{boundary_type}", line: 0, column: 0, path: @ctx.current_analysis_path) unless converted
143
110
 
144
- def inlineable_foreign_argument_expression?(expression)
145
- case expression
146
- when IR::Name, IR::IntegerLiteral, IR::FloatLiteral, IR::StringLiteral, IR::BooleanLiteral, IR::NullLiteral, IR::ZeroInit, IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
147
- true
148
- when IR::Call
149
- return false if temporary_foreign_cstr_expression?(expression)
150
-
151
- callee_inlineable = expression.callee.is_a?(String) || inlineable_foreign_argument_expression?(expression.callee)
152
- callee_inlineable && expression.arguments.all? { |argument| inlineable_foreign_argument_expression?(argument) }
153
- when IR::Member
154
- inlineable_foreign_argument_expression?(expression.receiver)
155
- when IR::Index
156
- inlineable_foreign_argument_expression?(expression.receiver) && inlineable_foreign_argument_expression?(expression.index)
157
- when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
158
- inlineable_foreign_argument_expression?(expression.receiver) && inlineable_foreign_argument_expression?(expression.index)
159
- when IR::Unary
160
- inlineable_foreign_argument_expression?(expression.operand)
161
- when IR::Binary
162
- inlineable_foreign_argument_expression?(expression.left) && inlineable_foreign_argument_expression?(expression.right)
163
- when IR::Conditional
164
- inlineable_foreign_argument_expression?(expression.condition) &&
165
- inlineable_foreign_argument_expression?(expression.then_expression) &&
166
- inlineable_foreign_argument_expression?(expression.else_expression)
167
- when IR::ReinterpretExpr, IR::Cast
168
- inlineable_foreign_argument_expression?(expression.expression)
169
- when IR::AddressOf
170
- inlineable_foreign_argument_expression?(expression.expression)
171
- when IR::AggregateLiteral
172
- expression.fields.all? { |field| inlineable_foreign_argument_expression?(field.value) }
173
- else
174
- false
175
- end
111
+ converted
176
112
  end
177
113
 
178
- def lower_contextual_expression(expression, env:, expected_type:, external_numeric: false, contextual_int_to_float: false)
179
- if string_literal_cstr_compatibility?(expression, expected_type)
180
- return IR::StringLiteral.new(value: expression.value, type: expected_type, cstring: true)
181
- end
182
-
183
- lowered = lower_expression(expression, env:, expected_type: expected_type)
184
- return lowered unless expected_type
185
- if (materialized = materialize_pointer_backed_value(lowered, expected_type))
186
- return materialized
187
- end
188
- return lowered if lowered.type == expected_type
189
- return lower_direct_function_to_proc_expression(expression, lowered, env:, expected_type:) if direct_function_to_proc_contextual_compatibility?(expression, lowered.type, env:, expected_type:)
190
- return lower_str_buffer_to_span_expression(lowered, expected_type) if str_buffer_to_span_compatible?(lowered.type, expected_type)
191
- return lower_array_to_span_expression(lowered, expected_type) if array_to_span_compatible?(lowered.type, expected_type)
192
- return cast_expression(lowered, expected_type) if contextual_numeric_compatibility?(expression, lowered.type, expected_type, env:, external_numeric:, contextual_int_to_float:)
193
-
194
- lowered
114
+ lowered << IR::LocalDecl.new(
115
+ name: items_name,
116
+ linkage_name: items_name,
117
+ type: items_array_type,
118
+ value: IR::ArrayLiteral.new(type: items_array_type, elements: items),
119
+ )
120
+
121
+ items_ref = IR::Name.new(name: items_name, type: items_array_type, pointer: false)
122
+ IR::AggregateLiteral.new(
123
+ type: boundary_type,
124
+ fields: [
125
+ IR::AggregateField.new(
126
+ name: "data",
127
+ value: IR::AddressOf.new(
128
+ expression: IR::Index.new(
129
+ receiver: items_ref,
130
+ index: IR::IntegerLiteral.new(value: 0, type: len_type),
131
+ type: boundary_element_type,
132
+ ),
133
+ type: pointer_to(boundary_element_type),
134
+ ),
135
+ ),
136
+ IR::AggregateField.new(name: "len", value: IR::IntegerLiteral.new(value: len, type: len_type)),
137
+ ],
138
+ )
139
+ end
140
+
141
+ def inlineable_foreign_argument_expression?(expression)
142
+ case expression
143
+ when IR::Name, IR::IntegerLiteral, IR::FloatLiteral, IR::StringLiteral, IR::BooleanLiteral, IR::NullLiteral, IR::ZeroInit, IR::SizeofExpr, IR::AlignofExpr, IR::OffsetofExpr
144
+ true
145
+ when IR::Call
146
+ return false if temporary_foreign_cstr_expression?(expression)
147
+
148
+ callee_inlineable = expression.callee.is_a?(String) || inlineable_foreign_argument_expression?(expression.callee)
149
+ callee_inlineable && expression.arguments.all? { |argument| inlineable_foreign_argument_expression?(argument) }
150
+ when IR::Member
151
+ inlineable_foreign_argument_expression?(expression.receiver)
152
+ when IR::Index
153
+ inlineable_foreign_argument_expression?(expression.receiver) && inlineable_foreign_argument_expression?(expression.index)
154
+ when IR::CheckedIndex, IR::CheckedSpanIndex, IR::NullableIndex, IR::NullableSpanIndex
155
+ inlineable_foreign_argument_expression?(expression.receiver) && inlineable_foreign_argument_expression?(expression.index)
156
+ when IR::Unary
157
+ inlineable_foreign_argument_expression?(expression.operand)
158
+ when IR::Binary
159
+ inlineable_foreign_argument_expression?(expression.left) && inlineable_foreign_argument_expression?(expression.right)
160
+ when IR::Conditional
161
+ inlineable_foreign_argument_expression?(expression.condition) &&
162
+ inlineable_foreign_argument_expression?(expression.then_expression) &&
163
+ inlineable_foreign_argument_expression?(expression.else_expression)
164
+ when IR::ReinterpretExpr, IR::Cast
165
+ inlineable_foreign_argument_expression?(expression.expression)
166
+ when IR::AddressOf
167
+ inlineable_foreign_argument_expression?(expression.expression)
168
+ when IR::AggregateLiteral
169
+ expression.fields.all? { |field| inlineable_foreign_argument_expression?(field.value) }
170
+ else
171
+ false
195
172
  end
173
+ end
196
174
 
197
- def materialize_pointer_backed_value(lowered, expected_type)
198
- return nil unless lowered.is_a?(IR::Name) && lowered.pointer
199
- return nil unless lowered.type == expected_type
200
- return nil if ref_type?(expected_type)
201
- return nil if pointer_type?(expected_type)
175
+ def lower_contextual_expression(expression, env:, expected_type:, external_numeric: false, contextual_int_to_float: false)
176
+ if string_literal_cstr_compatibility?(expression, expected_type)
177
+ return IR::StringLiteral.new(value: expression.value, type: expected_type, cstring: true)
178
+ end
202
179
 
203
- IR::Unary.new(operator: "*", operand: lowered, type: lowered.type)
180
+ lowered = lower_expression(expression, env:, expected_type: expected_type)
181
+ return lowered unless expected_type
182
+ if (materialized = materialize_pointer_backed_value(lowered, expected_type))
183
+ return materialized
204
184
  end
185
+ return lowered if lowered.type == expected_type
186
+ return lower_direct_function_to_proc_expression(expression, lowered, env:, expected_type:) if direct_function_to_proc_contextual_compatibility?(expression, lowered.type, env:, expected_type:)
187
+ return lower_str_buffer_to_span_expression(lowered, expected_type) if str_buffer_to_span_compatible?(lowered.type, expected_type)
188
+ return lower_array_to_span_expression(lowered, expected_type) if array_to_span_compatible?(lowered.type, expected_type)
189
+ return cast_expression(lowered, expected_type) if contextual_numeric_compatibility?(expression, lowered.type, expected_type, env:, external_numeric:, contextual_int_to_float:)
190
+
191
+ lowered
192
+ end
193
+
194
+ def materialize_pointer_backed_value(lowered, expected_type)
195
+ return nil unless lowered.is_a?(IR::Name) && lowered.pointer
196
+ return nil unless lowered.type == expected_type
197
+ return nil if ref_type?(expected_type)
198
+ return nil if pointer_type?(expected_type)
199
+
200
+ IR::Unary.new(operator: "*", operand: lowered, type: lowered.type)
201
+ end
205
202
  end
206
203
  end