mt-lang 0.3.9 → 0.3.11

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 (204) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/docs/language-design.md +1 -2
  4. data/docs/language-manual.md +12 -1
  5. data/lib/milk_tea/base.rb +1 -2
  6. data/lib/milk_tea/bindings/bindgen/ast_parser.rb +0 -2
  7. data/lib/milk_tea/bindings/bindgen/declaration.rb +0 -2
  8. data/lib/milk_tea/bindings/bindgen/emitter.rb +0 -2
  9. data/lib/milk_tea/bindings/bindgen/overrides.rb +0 -2
  10. data/lib/milk_tea/bindings/bindgen/type_mapper.rb +51 -53
  11. data/lib/milk_tea/bindings/imported_bindings/generator.rb +7 -9
  12. data/lib/milk_tea/bindings/imported_bindings/method_source.rb +0 -2
  13. data/lib/milk_tea/bindings/imported_bindings/naming.rb +6 -8
  14. data/lib/milk_tea/bindings/imported_bindings.rb +0 -2
  15. data/lib/milk_tea/bindings/opengl_registry.rb +3 -7
  16. data/lib/milk_tea/bindings/steamworks.rb +12 -16
  17. data/lib/milk_tea/bindings/upstream_sources.rb +10 -14
  18. data/lib/milk_tea/bindings/vendored_box2d.rb +10 -12
  19. data/lib/milk_tea/bindings/vendored_cjson.rb +6 -8
  20. data/lib/milk_tea/bindings/vendored_flecs.rb +10 -12
  21. data/lib/milk_tea/bindings/vendored_glfw.rb +11 -13
  22. data/lib/milk_tea/bindings/vendored_libuv.rb +11 -13
  23. data/lib/milk_tea/bindings/vendored_pcre2.rb +11 -13
  24. data/lib/milk_tea/bindings/vendored_raylib.rb +6 -10
  25. data/lib/milk_tea/bindings/vendored_sdl3.rb +11 -13
  26. data/lib/milk_tea/bindings/vendored_steamworks.rb +1 -5
  27. data/lib/milk_tea/core/ast.rb +109 -51
  28. data/lib/milk_tea/core/async_runtime_installer.rb +0 -2
  29. data/lib/milk_tea/core/bindings/attribute_binding.rb +1 -3
  30. data/lib/milk_tea/core/c_backend/aggregate_utils.rb +147 -84
  31. data/lib/milk_tea/core/c_backend/control_flow_emission.rb +394 -396
  32. data/lib/milk_tea/core/c_backend/expressions.rb +489 -476
  33. data/lib/milk_tea/core/c_backend/feature_detection.rb +446 -437
  34. data/lib/milk_tea/core/c_backend/format_helpers.rb +0 -2
  35. data/lib/milk_tea/core/c_backend/reachability.rb +339 -341
  36. data/lib/milk_tea/core/c_backend/reinterpret.rb +231 -217
  37. data/lib/milk_tea/core/c_backend/runtime_helpers.rb +531 -526
  38. data/lib/milk_tea/core/c_backend/statements.rb +528 -530
  39. data/lib/milk_tea/core/c_backend/type_collectors.rb +1344 -1346
  40. data/lib/milk_tea/core/c_backend/type_declaration.rb +215 -213
  41. data/lib/milk_tea/core/c_backend/type_system.rb +347 -349
  42. data/lib/milk_tea/core/c_backend.rb +17 -9
  43. data/lib/milk_tea/core/compatibility_helpers.rb +0 -2
  44. data/lib/milk_tea/core/compile_time/const_eval.rb +7 -12
  45. data/lib/milk_tea/core/compile_time.rb +32 -38
  46. data/lib/milk_tea/core/control_flow/builder.rb +3 -5
  47. data/lib/milk_tea/core/control_flow/constant_propagation.rb +14 -17
  48. data/lib/milk_tea/core/control_flow/definite_assignment.rb +0 -1
  49. data/lib/milk_tea/core/ir.rb +10 -10
  50. data/lib/milk_tea/core/lexer/character_classes.rb +5 -7
  51. data/lib/milk_tea/core/lexer/format_strings.rb +7 -9
  52. data/lib/milk_tea/core/lexer/heredocs.rb +22 -22
  53. data/lib/milk_tea/core/lexer/indentation.rb +0 -2
  54. data/lib/milk_tea/core/lexer/numbers.rb +0 -2
  55. data/lib/milk_tea/core/lexer/recovery.rb +0 -2
  56. data/lib/milk_tea/core/lexer/strings.rb +0 -2
  57. data/lib/milk_tea/core/lexer/symbols.rb +0 -2
  58. data/lib/milk_tea/core/lexer/trivia.rb +0 -2
  59. data/lib/milk_tea/core/lexer.rb +0 -2
  60. data/lib/milk_tea/core/lowering/async/analysis.rb +0 -2
  61. data/lib/milk_tea/core/lowering/async/lowering.rb +1264 -1265
  62. data/lib/milk_tea/core/lowering/async/normalization.rb +5 -3
  63. data/lib/milk_tea/core/lowering/async.rb +627 -630
  64. data/lib/milk_tea/core/lowering/block.rb +413 -416
  65. data/lib/milk_tea/core/lowering/calls.rb +1381 -1384
  66. data/lib/milk_tea/core/lowering/declarations.rb +180 -183
  67. data/lib/milk_tea/core/lowering/dyn.rb +48 -50
  68. data/lib/milk_tea/core/lowering/events.rb +983 -985
  69. data/lib/milk_tea/core/lowering/expressions.rb +1513 -1518
  70. data/lib/milk_tea/core/lowering/foreign_cstr.rb +181 -184
  71. data/lib/milk_tea/core/lowering/functions.rb +185 -188
  72. data/lib/milk_tea/core/lowering/loops.rb +1028 -1031
  73. data/lib/milk_tea/core/lowering/proc.rb +363 -366
  74. data/lib/milk_tea/core/lowering/resolve.rb +2133 -2135
  75. data/lib/milk_tea/core/lowering/scans.rb +179 -181
  76. data/lib/milk_tea/core/lowering/str_buffer.rb +102 -105
  77. data/lib/milk_tea/core/lowering/utils.rb +1040 -1044
  78. data/lib/milk_tea/core/lowering.rb +5 -7
  79. data/lib/milk_tea/core/module_binder.rb +0 -2
  80. data/lib/milk_tea/core/module_loader/errors.rb +4 -2
  81. data/lib/milk_tea/core/module_loader.rb +113 -20
  82. data/lib/milk_tea/core/module_path_resolver.rb +0 -2
  83. data/lib/milk_tea/core/module_roots.rb +6 -8
  84. data/lib/milk_tea/core/parser/attributes.rb +0 -2
  85. data/lib/milk_tea/core/parser/blocks.rb +0 -2
  86. data/lib/milk_tea/core/parser/declarations.rb +7 -9
  87. data/lib/milk_tea/core/parser/expressions.rb +15 -10
  88. data/lib/milk_tea/core/parser/recovery.rb +0 -2
  89. data/lib/milk_tea/core/parser/statements.rb +8 -2
  90. data/lib/milk_tea/core/parser/types.rb +12 -14
  91. data/lib/milk_tea/core/parser.rb +0 -2
  92. data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +31 -33
  93. data/lib/milk_tea/core/pretty_printer/base_formatter.rb +0 -2
  94. data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +0 -2
  95. data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +0 -2
  96. data/lib/milk_tea/core/semantic_analyzer/attributes.rb +14 -16
  97. data/lib/milk_tea/core/semantic_analyzer/calls.rb +0 -2
  98. data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1 -14
  99. data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +18 -21
  100. data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +0 -3
  101. data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +14 -17
  102. data/lib/milk_tea/core/semantic_analyzer/generics.rb +57 -59
  103. data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +0 -2
  104. data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +5 -9
  105. data/lib/milk_tea/core/semantic_analyzer/nullability.rb +0 -3
  106. data/lib/milk_tea/core/semantic_analyzer/statements.rb +35 -40
  107. data/lib/milk_tea/core/semantic_analyzer/top_level.rb +10 -12
  108. data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +0 -6
  109. data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +106 -109
  110. data/lib/milk_tea/core/semantic_analyzer.rb +17 -8
  111. data/lib/milk_tea/core/types/layout.rb +21 -22
  112. data/lib/milk_tea/core/types/predicates.rb +0 -2
  113. data/lib/milk_tea/core/types/registry.rb +16 -18
  114. data/lib/milk_tea/core/types/visitor.rb +0 -4
  115. data/lib/milk_tea/dap/backends/lldb_dap.rb +0 -2
  116. data/lib/milk_tea/dap/protocol.rb +1 -1
  117. data/lib/milk_tea/dap/server/breakpoints.rb +0 -2
  118. data/lib/milk_tea/dap/server/debug_map.rb +0 -2
  119. data/lib/milk_tea/dap/server/handlers.rb +0 -2
  120. data/lib/milk_tea/dap/server/launch.rb +0 -2
  121. data/lib/milk_tea/dap/server/lldb_backend.rb +8 -10
  122. data/lib/milk_tea/dap/server/pause_diagnostics.rb +14 -16
  123. data/lib/milk_tea/dap/server/utilities.rb +0 -2
  124. data/lib/milk_tea/dap/server/wire.rb +0 -2
  125. data/lib/milk_tea/dap/server.rb +0 -2
  126. data/lib/milk_tea/lsp/diagnostics.rb +16 -16
  127. data/lib/milk_tea/lsp/server/call_hierarchy.rb +11 -12
  128. data/lib/milk_tea/lsp/server/code_actions.rb +355 -357
  129. data/lib/milk_tea/lsp/server/code_lens.rb +23 -25
  130. data/lib/milk_tea/lsp/server/completion.rb +873 -875
  131. data/lib/milk_tea/lsp/server/configuration.rb +129 -131
  132. data/lib/milk_tea/lsp/server/debug_info.rb +0 -2
  133. data/lib/milk_tea/lsp/server/definition.rb +564 -565
  134. data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +191 -193
  135. data/lib/milk_tea/lsp/server/execute_command.rb +0 -2
  136. data/lib/milk_tea/lsp/server/folding_range.rb +0 -4
  137. data/lib/milk_tea/lsp/server/formatting.rb +478 -480
  138. data/lib/milk_tea/lsp/server/hover.rb +1282 -1284
  139. data/lib/milk_tea/lsp/server/inlay_hints.rb +179 -181
  140. data/lib/milk_tea/lsp/server/lifecycle.rb +192 -194
  141. data/lib/milk_tea/lsp/server/linked_editing_range.rb +0 -2
  142. data/lib/milk_tea/lsp/server/on_type_formatting.rb +0 -2
  143. data/lib/milk_tea/lsp/server/progress.rb +0 -2
  144. data/lib/milk_tea/lsp/server/references.rb +316 -318
  145. data/lib/milk_tea/lsp/server/rename.rb +445 -447
  146. data/lib/milk_tea/lsp/server/selection_range.rb +0 -4
  147. data/lib/milk_tea/lsp/server/semantic_tokens.rb +1376 -1314
  148. data/lib/milk_tea/lsp/server/signature_help.rb +146 -148
  149. data/lib/milk_tea/lsp/server/text_documents.rb +99 -101
  150. data/lib/milk_tea/lsp/server/type_hierarchy.rb +2 -4
  151. data/lib/milk_tea/lsp/server/utilities.rb +397 -399
  152. data/lib/milk_tea/lsp/server.rb +0 -3
  153. data/lib/milk_tea/lsp/workspace/analysis.rb +40 -42
  154. data/lib/milk_tea/lsp/workspace/dependency_graph.rb +4 -10
  155. data/lib/milk_tea/lsp/workspace/utilities.rb +19 -19
  156. data/lib/milk_tea/packages/atomic_write.rb +4 -5
  157. data/lib/milk_tea/packages/dependency_solver.rb +15 -15
  158. data/lib/milk_tea/packages/lock.rb +4 -4
  159. data/lib/milk_tea/packages/manager_cli.rb +1 -1
  160. data/lib/milk_tea/packages/manifest.rb +3 -3
  161. data/lib/milk_tea/packages/registry_store.rb +4 -6
  162. data/lib/milk_tea/packages/services.rb +16 -16
  163. data/lib/milk_tea/packages/source_cache.rb +4 -6
  164. data/lib/milk_tea/packages/source_resolver.rb +44 -44
  165. data/lib/milk_tea/packages/version.rb +8 -8
  166. data/lib/milk_tea/tooling/build.rb +3 -7
  167. data/lib/milk_tea/tooling/build_cache.rb +0 -2
  168. data/lib/milk_tea/tooling/cli.rb +10 -4
  169. data/lib/milk_tea/tooling/debug_info_formatter.rb +31 -33
  170. data/lib/milk_tea/tooling/debug_map.rb +8 -10
  171. data/lib/milk_tea/tooling/docs_app.rb +0 -2
  172. data/lib/milk_tea/tooling/linter/doc_tags.rb +25 -27
  173. data/lib/milk_tea/tooling/linter/fix_engine.rb +87 -24
  174. data/lib/milk_tea/tooling/linter/flow_rules.rb +44 -46
  175. data/lib/milk_tea/tooling/linter/imports_platform.rb +14 -16
  176. data/lib/milk_tea/tooling/linter/release_rules.rb +3 -5
  177. data/lib/milk_tea/tooling/linter/reserved_names.rb +23 -25
  178. data/lib/milk_tea/tooling/linter/rules.rb +87 -89
  179. data/lib/milk_tea/tooling/linter/source_helpers.rb +40 -42
  180. data/lib/milk_tea/tooling/linter/trailing_comma.rb +17 -19
  181. data/lib/milk_tea/tooling/linter/visitors.rb +112 -54
  182. data/lib/milk_tea/tooling/linter.rb +0 -2
  183. data/lib/milk_tea/tooling/project_scaffold.rb +0 -2
  184. data/lib/milk_tea/tooling/run.rb +0 -2
  185. data/lib/milk_tea/tooling/toolchain_cli.rb +0 -2
  186. data/std/cli.mt +13 -32
  187. data/std/color.mt +28 -28
  188. data/std/encoding.mt +4 -4
  189. data/std/graph.mt +1 -2
  190. data/std/hash.mt +14 -14
  191. data/std/http/server.mt +3 -3
  192. data/std/input.mt +1 -1
  193. data/std/json.mt +1 -1
  194. data/std/linear_algebra.mt +6 -6
  195. data/std/net/mux.mt +1 -1
  196. data/std/noise.mt +23 -23
  197. data/std/parse.mt +2 -2
  198. data/std/process.mt +3 -4
  199. data/std/sparse_set.mt +1 -1
  200. data/std/steering.mt +5 -5
  201. data/std/str.mt +1 -1
  202. data/std/tween.mt +4 -4
  203. data/std/utility.mt +3 -3
  204. 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