mt-lang 0.3.4 → 0.3.5

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.
@@ -1672,5 +1672,99 @@ module MilkTea
1672
1672
  end
1673
1673
  expr
1674
1674
  end
1675
+
1676
+ def prepare_result_propagation_for_inline_lowering(expression, env:, allow_void_success: false)
1677
+ storage_type, success_type, return_type, error_type = infer_result_propagation_types(expression, env:, allow_void_success:)
1678
+ is_option = option_let_else_type?(storage_type)
1679
+
1680
+ env[:prepared_expression_cleanups] ||= []
1681
+ cleanup_start = env[:prepared_expression_cleanups].length
1682
+ operand_setup, operand = prepare_expression_for_inline_lowering(expression.operand, env:, expected_type: storage_type)
1683
+ operand_cleanups = env[:prepared_expression_cleanups].drop(cleanup_start)
1684
+
1685
+ result_name = fresh_c_temp_name(env, "propagate")
1686
+ result_ref = IR::Name.new(name: result_name, type: storage_type, pointer: false)
1687
+ return_context = env.fetch(:return_context)
1688
+ failure_return = if storage_type == return_type
1689
+ result_ref
1690
+ elsif is_option
1691
+ IR::VariantLiteral.new(
1692
+ type: return_type,
1693
+ arm_name: "none",
1694
+ fields: [],
1695
+ )
1696
+ else
1697
+ IR::VariantLiteral.new(
1698
+ type: return_type,
1699
+ arm_name: "failure",
1700
+ fields: [
1701
+ IR::AggregateField.new(
1702
+ name: "error",
1703
+ value: variant_binding_projection_expression(result_ref, storage_type, "failure", "error", error_type),
1704
+ ),
1705
+ ],
1706
+ )
1707
+ end
1708
+ failure_cleanup = operand_cleanups.flat_map(&:itself)
1709
+ failure_terminator = if return_context[:async_info]
1710
+ failure_cleanup +
1711
+ lower_async_cleanup_entries(
1712
+ return_context[:local_defers],
1713
+ return_context[:active_defers],
1714
+ frame_expr: return_context.fetch(:frame_expr),
1715
+ raw_frame_expr: return_context.fetch(:raw_frame_expr),
1716
+ async_info: return_context.fetch(:async_info),
1717
+ ) +
1718
+ async_complete_statements(
1719
+ frame_expr: return_context.fetch(:frame_expr),
1720
+ raw_frame_expr: return_context.fetch(:raw_frame_expr),
1721
+ async_info: return_context.fetch(:async_info),
1722
+ value: failure_return,
1723
+ )
1724
+ else
1725
+ failure_cleanup +
1726
+ cleanup_statements(return_context[:local_defers], return_context[:active_defers]) +
1727
+ [IR::ReturnStmt.new(value: failure_return, source_path: @ctx.current_analysis_path)]
1728
+ end
1729
+
1730
+ if success_type == @ctx.types.fetch("void")
1731
+ return [
1732
+ operand_setup + [
1733
+ IR::LocalDecl.new(
1734
+ name: result_name,
1735
+ linkage_name: result_name,
1736
+ type: storage_type,
1737
+ value: lower_contextual_expression(operand, env:, expected_type: storage_type),
1738
+ ),
1739
+ IR::IfStmt.new(
1740
+ condition: let_else_failure_condition(result_ref, storage_type),
1741
+ then_body: failure_terminator,
1742
+ else_body: nil,
1743
+ ),
1744
+ ],
1745
+ nil,
1746
+ ]
1747
+ end
1748
+
1749
+ projection = is_option ? :option_some_value : :result_success_value
1750
+ register_prepared_temp!(env, result_name, success_type, storage_type:, projection:)
1751
+
1752
+ [
1753
+ operand_setup + [
1754
+ IR::LocalDecl.new(
1755
+ name: result_name,
1756
+ linkage_name: result_name,
1757
+ type: storage_type,
1758
+ value: lower_contextual_expression(operand, env:, expected_type: storage_type),
1759
+ ),
1760
+ IR::IfStmt.new(
1761
+ condition: let_else_failure_condition(result_ref, storage_type),
1762
+ then_body: failure_terminator,
1763
+ else_body: nil,
1764
+ ),
1765
+ ],
1766
+ AST::Identifier.new(name: result_name),
1767
+ ]
1768
+ end
1675
1769
  end
1676
1770
  end
@@ -1083,5 +1083,54 @@ module MilkTea
1083
1083
  end
1084
1084
  end
1085
1085
 
1086
+ def iterator_loop_info(type, env:)
1087
+ iter_name = "__mt_for_iterable__"
1088
+ iterator_name = "__mt_for_iterator__"
1089
+ probe_env = duplicate_env(env)
1090
+ current_actual_scope(probe_env[:scopes])[iter_name] = local_binding(type:, linkage_name: iter_name, mutable: false, pointer: false)
1091
+
1092
+ iter_call = AST::Call.new(
1093
+ callee: AST::MemberAccess.new(receiver: AST::Identifier.new(name: iter_name), member: "iter"),
1094
+ arguments: [],
1095
+ )
1096
+ iterator_type = infer_expression_type(iter_call, env: probe_env)
1097
+
1098
+ current_actual_scope(probe_env[:scopes])[iterator_name] = local_binding(type: iterator_type, linkage_name: iterator_name, mutable: true, pointer: false)
1099
+ next_call = AST::Call.new(
1100
+ callee: AST::MemberAccess.new(receiver: AST::Identifier.new(name: iterator_name), member: "next"),
1101
+ arguments: [],
1102
+ )
1103
+ item_storage_type = infer_expression_type(next_call, env: probe_env)
1104
+ if item_storage_type.is_a?(Types::Nullable) && nullable_iterator_item_type?(item_storage_type.base)
1105
+ return {
1106
+ kind: :nullable_item,
1107
+ iterator_type:,
1108
+ item_storage_type:,
1109
+ item_type: item_storage_type.base,
1110
+ }
1111
+ end
1112
+
1113
+ if item_storage_type == @ctx.types.fetch("bool")
1114
+ current_call = AST::Call.new(
1115
+ callee: AST::MemberAccess.new(receiver: AST::Identifier.new(name: iterator_name), member: "current"),
1116
+ arguments: [],
1117
+ )
1118
+ current_type = infer_expression_type(current_call, env: probe_env)
1119
+ return {
1120
+ kind: :current_item,
1121
+ iterator_type:,
1122
+ item_storage_type: current_type,
1123
+ item_type: current_type,
1124
+ }
1125
+ end
1126
+
1127
+ nil
1128
+ rescue LoweringError
1129
+ nil
1130
+ end
1131
+
1132
+ def nullable_iterator_item_type?(type)
1133
+ type == @ctx.types.fetch("cstr") || pointer_type?(type)
1134
+ end
1086
1135
  end
1087
1136
  end