1
- use cairo_lang_debug:: DebugWithDb ;
2
1
use cairo_lang_diagnostics:: Maybe ;
3
2
use cairo_lang_semantic as semantic;
4
- use cairo_lang_semantic:: corelib;
5
3
use cairo_lang_syntax:: node:: TypedStablePtr ;
6
- use semantic:: { Condition , MatchArmSelector } ;
7
4
8
5
use super :: block_builder:: { BlockBuilder , SealedBlockBuilder } ;
9
- use super :: context:: { LoweredExpr , LoweringContext , LoweringFlowError , LoweringResult } ;
6
+ use super :: context:: { LoweredExpr , LoweringContext , LoweringResult } ;
10
7
use super :: flow_control:: create_graph:: create_graph_expr_if;
11
8
use super :: flow_control:: lower_graph:: lower_graph;
12
9
use super :: lowered_expr_to_block_scope_end;
13
- use crate :: diagnostic:: LoweringDiagnosticKind :: { self } ;
14
- use crate :: diagnostic:: { LoweringDiagnosticsBuilder , MatchDiagnostic , MatchError , MatchKind } ;
15
10
use crate :: ids:: LocationId ;
16
- use crate :: lower:: context:: VarRequest ;
17
- use crate :: lower:: lower_match:: { self , MatchArmWrapper } ;
18
- use crate :: lower:: { create_subscope, lower_block, lower_expr, lower_expr_to_var_usage} ;
19
- use crate :: { MatchArm , MatchEnumInfo , MatchInfo } ;
20
-
21
- /// Represents an expression of the form:
22
- ///
23
- /// `if conditions[0] && conditions[1] && ... && conditions[n] { expr } else { else_block }`
24
- ///
25
- /// where `n` is `conditions.len() - 1`.
26
- ///
27
- /// In particular, note that if `conditions` is empty, there are no conditions and the
28
- /// expression is simply [Self::expr].
29
- pub struct ConditionedExpr < ' db , ' a > {
30
- pub expr : semantic:: ExprId ,
31
- pub conditions : & ' a [ Condition ] ,
32
- pub else_block : Option < semantic:: ExprId > ,
33
- /// The location of the `if` expression.
34
- pub if_expr_location : LocationId < ' db > ,
35
- }
36
-
37
- impl ConditionedExpr < ' _ , ' _ > {
38
- /// Returns a copy of self, without the first condition.
39
- pub fn remove_first ( & self ) -> Self {
40
- Self { conditions : & self . conditions [ 1 ..] , ..* self }
41
- }
42
- }
11
+ use crate :: lower:: lower_block;
43
12
44
13
/// Lowers an expression of type [semantic::ExprIf].
45
14
pub fn lower_expr_if < ' db > (
@@ -51,143 +20,6 @@ pub fn lower_expr_if<'db>(
51
20
lower_graph ( ctx, builder, & graph, ctx. get_location ( expr. stable_ptr . untyped ( ) ) )
52
21
}
53
22
54
- /// Lowers an expression of type [semantic::ExprIf].
55
- pub fn lower_if_bool_condition < ' db > (
56
- ctx : & mut LoweringContext < ' db , ' _ > ,
57
- builder : & mut BlockBuilder < ' db > ,
58
- condition : semantic:: ExprId ,
59
- inner_expr : ConditionedExpr < ' db , ' _ > ,
60
- ) -> LoweringResult < ' db , LoweredExpr < ' db > > {
61
- // The condition cannot be unit.
62
- let condition_var = lower_expr_to_var_usage ( ctx, builder, condition) ?;
63
- let db = ctx. db ;
64
- let unit_ty = corelib:: unit_ty ( db) ;
65
-
66
- let if_expr_location = inner_expr. if_expr_location ;
67
-
68
- // Main block.
69
- let subscope_main = create_subscope ( ctx, builder) ;
70
- let block_main_id = subscope_main. block_id ;
71
- let main_block_var_id = ctx. new_var ( VarRequest { ty : unit_ty, location : if_expr_location } ) ;
72
- let else_block_input_var_id =
73
- ctx. new_var ( VarRequest { ty : unit_ty, location : if_expr_location } ) ;
74
-
75
- let block_main = lower_conditioned_expr_and_seal ( ctx, subscope_main, & inner_expr)
76
- . map_err ( LoweringFlowError :: Failed ) ?;
77
-
78
- // Else block.
79
- let subscope_else = create_subscope ( ctx, builder) ;
80
- let block_else_id = subscope_else. block_id ;
81
-
82
- let block_else =
83
- lower_optional_else_block ( ctx, subscope_else, inner_expr. else_block , if_expr_location)
84
- . map_err ( LoweringFlowError :: Failed ) ?;
85
-
86
- let match_info = MatchInfo :: Enum ( MatchEnumInfo {
87
- concrete_enum_id : corelib:: core_bool_enum ( db) ,
88
- input : condition_var,
89
- arms : vec ! [
90
- MatchArm {
91
- arm_selector: MatchArmSelector :: VariantId ( corelib:: false_variant( db) ) ,
92
- block_id: block_else_id,
93
- var_ids: vec![ else_block_input_var_id] ,
94
- } ,
95
- MatchArm {
96
- arm_selector: MatchArmSelector :: VariantId ( corelib:: true_variant( db) ) ,
97
- block_id: block_main_id,
98
- var_ids: vec![ main_block_var_id] ,
99
- } ,
100
- ] ,
101
- location : if_expr_location,
102
- } ) ;
103
- builder. merge_and_end_with_match (
104
- ctx,
105
- match_info,
106
- vec ! [ block_main, block_else] ,
107
- if_expr_location,
108
- )
109
- }
110
-
111
- /// Lowers an expression of type if where the condition is of type [semantic::Condition::Let].
112
- pub fn lower_if_let_condition < ' db > (
113
- ctx : & mut LoweringContext < ' db , ' _ > ,
114
- builder : & mut BlockBuilder < ' db > ,
115
- matched_expr_id : semantic:: ExprId ,
116
- patterns : & [ semantic:: PatternId ] ,
117
- inner_expr : ConditionedExpr < ' db , ' _ > ,
118
- ) -> LoweringResult < ' db , LoweredExpr < ' db > > {
119
- let matched_expr = & ctx. function_body . arenas . exprs [ matched_expr_id] ;
120
- let stable_ptr = matched_expr. stable_ptr ( ) . untyped ( ) ;
121
- let ty = matched_expr. ty ( ) ;
122
- let location = ctx. get_location ( stable_ptr) ;
123
-
124
- let lowered_expr = lower_expr ( ctx, builder, matched_expr_id) ?;
125
-
126
- if corelib:: numeric_upcastable_to_felt252 ( ctx. db , ty) {
127
- return Err ( LoweringFlowError :: Failed ( ctx. diagnostics . report (
128
- stable_ptr,
129
- LoweringDiagnosticKind :: MatchError ( MatchError {
130
- kind : MatchKind :: IfLet ,
131
- error : MatchDiagnostic :: UnsupportedNumericInLetCondition ,
132
- } ) ,
133
- ) ) ) ;
134
- }
135
-
136
- let else_arm = inner_expr
137
- . else_block
138
- . map ( MatchArmWrapper :: ElseClause )
139
- . unwrap_or ( MatchArmWrapper :: DefaultClause ) ;
140
- let arms = vec ! [ MatchArmWrapper :: ConditionedArm ( patterns, inner_expr) , else_arm] ;
141
-
142
- lower_match:: lower_match_arms (
143
- ctx,
144
- builder,
145
- matched_expr_id,
146
- lowered_expr,
147
- arms,
148
- location,
149
- MatchKind :: IfLet ,
150
- )
151
- }
152
-
153
- /// Lowers a [ConditionedExpr] recursively by iterating over the conditions and calling
154
- /// [lower_if_let_condition] or [lower_if_bool_condition].
155
- fn lower_conditioned_expr < ' db > (
156
- ctx : & mut LoweringContext < ' db , ' _ > ,
157
- builder : & mut BlockBuilder < ' db > ,
158
- expr : & ConditionedExpr < ' db , ' _ > ,
159
- ) -> LoweringResult < ' db , LoweredExpr < ' db > > {
160
- log:: trace!(
161
- "Lowering a conditioned expression: {:?} (# of conditions: {})" ,
162
- expr. expr. debug( & ctx. expr_formatter) ,
163
- expr. conditions. len( )
164
- ) ;
165
-
166
- // If there are no more conditions, we can simply lower the expression.
167
- if expr. conditions . is_empty ( ) {
168
- return lower_expr ( ctx, builder, expr. expr ) ;
169
- }
170
-
171
- match & expr. conditions [ 0 ] {
172
- Condition :: Let ( matched_expr_id, patterns) => {
173
- lower_if_let_condition ( ctx, builder, * matched_expr_id, patterns, expr. remove_first ( ) )
174
- }
175
- Condition :: BoolExpr ( condition) => {
176
- lower_if_bool_condition ( ctx, builder, * condition, expr. remove_first ( ) )
177
- }
178
- }
179
- }
180
-
181
- /// Lowers a [ConditionedExpr] and seals the block. See [lower_conditioned_expr].
182
- pub fn lower_conditioned_expr_and_seal < ' db > (
183
- ctx : & mut LoweringContext < ' db , ' _ > ,
184
- mut builder : BlockBuilder < ' db > ,
185
- expr : & ConditionedExpr < ' db , ' _ > ,
186
- ) -> Maybe < SealedBlockBuilder < ' db > > {
187
- let lowered_expr = lower_conditioned_expr ( ctx, & mut builder, expr) ;
188
- lowered_expr_to_block_scope_end ( ctx, builder, lowered_expr)
189
- }
190
-
191
23
/// Lowers an optional else block. If the else block is missing it is replaced with a block
192
24
/// returning a unit.
193
25
/// Returns the sealed block builder of the else block.
0 commit comments