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.
- checksums.yaml +4 -4
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/core/c_backend/feature_detection.rb +27 -55
- data/lib/milk_tea/core/c_backend/format_helpers.rb +551 -0
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +0 -542
- data/lib/milk_tea/core/c_backend/type_collectors.rb +51 -204
- data/lib/milk_tea/core/c_backend.rb +2 -0
- data/lib/milk_tea/core/compatibility_helpers.rb +1 -1
- data/lib/milk_tea/core/lowering/async/lowering.rb +147 -141
- data/lib/milk_tea/core/lowering/block.rb +759 -725
- data/lib/milk_tea/core/lowering/expressions.rb +94 -0
- data/lib/milk_tea/core/lowering/loops.rb +49 -0
- data/lib/milk_tea/core/lowering/resolve.rb +221 -214
- data/lib/milk_tea/core/lowering/utils.rb +0 -222
- data/lib/milk_tea/core/module_loader.rb +29 -48
- data/lib/milk_tea/core/parser/declarations.rb +2 -2
- data/lib/milk_tea/core/parser/recovery.rb +1 -1
- data/lib/milk_tea/core/parser.rb +1 -1
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +3 -120
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +116 -113
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +346 -343
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +37 -12
- data/lib/milk_tea/core/types/predicates.rb +501 -499
- data/lib/milk_tea/core/types/visitor.rb +1 -1
- metadata +3 -2
|
@@ -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
|