@@ -150,6 +150,69 @@ Vec<ASR::stmt_t*> replace_selectcase(Allocator &al, const ASR::Select_t &select_
150
150
return body;
151
151
}
152
152
153
+ void case_to_if_with_fall_through (Allocator& al, const ASR::Select_t& x,
154
+ ASR::expr_t * a_test, Vec<ASR::stmt_t *>& body, SymbolTable* scope) {
155
+ body.reserve (al, x.n_body + 1 );
156
+ const Location& loc = x.base .base .loc ;
157
+ ASR::symbol_t * case_found_sym = ASR::down_cast<ASR::symbol_t >(ASR::make_Variable_t (
158
+ al, loc, scope, s2c (al, scope->get_unique_name (" case_found" )), nullptr , 0 ,
159
+ ASR::intentType::Local, nullptr , nullptr , ASR::storage_typeType::Default,
160
+ ASRUtils::TYPE (ASR::make_Logical_t (al, loc, 4 )), nullptr , ASR::abiType::Source,
161
+ ASR::accessType::Public, ASR::presenceType::Required, false ));
162
+ scope->add_symbol (scope->get_unique_name (" case_found" ), case_found_sym);
163
+ ASR::expr_t * true_asr = ASRUtils::EXPR (ASR::make_LogicalConstant_t (al, loc, true ,
164
+ ASRUtils::TYPE (ASR::make_Logical_t (al, loc, 4 ))));
165
+ ASR::expr_t * false_asr = ASRUtils::EXPR (ASR::make_LogicalConstant_t (al, loc, false ,
166
+ ASRUtils::TYPE (ASR::make_Logical_t (al, loc, 4 ))));
167
+ ASR::expr_t * case_found = ASRUtils::EXPR (ASR::make_Var_t (al, loc, case_found_sym));
168
+ body.push_back (al, ASRUtils::STMT (ASR::make_Assignment_t (al, loc, case_found, false_asr, nullptr )));
169
+ int label_id = ASRUtils::LabelGenerator::get_instance ()->get_unique_label ();
170
+ for ( int idx = 0 ; idx < x.n_body ; idx++ ) {
171
+ ASR::case_stmt_t * case_body = x.m_body [idx];
172
+ switch (case_body->type ) {
173
+ case ASR::case_stmtType::CaseStmt: {
174
+ ASR::CaseStmt_t* Case_Stmt = ASR::down_cast<ASR::CaseStmt_t>(case_body);
175
+ ASR::expr_t * test_expr = gen_test_expr_CaseStmt (al, loc, Case_Stmt, a_test);
176
+ test_expr = ASRUtils::EXPR (ASR::make_LogicalBinOp_t (al, loc, test_expr,
177
+ ASR::logicalbinopType::Or, case_found, ASRUtils::expr_type (case_found), nullptr ));
178
+ Vec<ASR::stmt_t *> case_body; case_body.reserve (al, Case_Stmt->n_body );
179
+ case_body.from_pointer_n (Case_Stmt->m_body , Case_Stmt->n_body );
180
+ case_body.push_back (al, ASRUtils::STMT (ASR::make_Assignment_t (
181
+ al, loc, case_found, true_asr, nullptr )));
182
+ if ( !Case_Stmt->m_fall_through ) {
183
+ case_body.push_back (al, ASRUtils::STMT (ASR::make_GoTo_t (al, loc,
184
+ label_id, s2c (al, scope->get_unique_name (" switch_case_label" )))));
185
+ }
186
+ body.push_back (al, ASRUtils::STMT (ASR::make_If_t (al, loc,
187
+ test_expr, case_body.p , case_body.size (), nullptr , 0 )));
188
+ break ;
189
+ }
190
+ case ASR::case_stmtType::CaseStmt_Range: {
191
+ LCOMPILERS_ASSERT (false );
192
+ break ;
193
+ }
194
+ }
195
+ }
196
+ for ( int id = 0 ; id < x.n_default ; id++ ) {
197
+ body.push_back (al, x.m_default [id]);
198
+ }
199
+ SymbolTable* block_symbol_table = al.make_new <SymbolTable>(scope);
200
+ ASR::symbol_t * empty_block = ASR::down_cast<ASR::symbol_t >(ASR::make_Block_t (
201
+ al, loc, block_symbol_table, s2c (al, scope->get_unique_name (" switch_case_label" )),
202
+ nullptr , 0 ));
203
+ scope->add_symbol (scope->get_unique_name (" switch_case_label" ), empty_block);
204
+ body.push_back (al, ASRUtils::STMT (ASR::make_BlockCall_t (al, loc, label_id, empty_block)));
205
+ }
206
+
207
+ Vec<ASR::stmt_t *> replace_selectcase_with_fall_through (
208
+ Allocator &al, const ASR::Select_t &select_case,
209
+ SymbolTable* scope) {
210
+ ASR::expr_t *a = select_case.m_test ;
211
+ Vec<ASR::stmt_t *> body;
212
+ case_to_if_with_fall_through (al, select_case, a, body, scope);
213
+ return body;
214
+ }
215
+
153
216
class SelectCaseVisitor : public PassUtils ::PassVisitor<SelectCaseVisitor>
154
217
{
155
218
@@ -165,7 +228,11 @@ class SelectCaseVisitor : public PassUtils::PassVisitor<SelectCaseVisitor>
165
228
}
166
229
167
230
void visit_Select (const ASR::Select_t &x) {
168
- pass_result = replace_selectcase (al, x);
231
+ if ( x.m_enable_fall_through ) {
232
+ pass_result = replace_selectcase_with_fall_through (al, x, current_scope);
233
+ } else {
234
+ pass_result = replace_selectcase (al, x);
235
+ }
169
236
}
170
237
};
171
238
0 commit comments