1use crate::analyzer_error::MismatchTypeKind;
2use crate::conv::utils::{
3 TypePosition, argument_list, build_for_range, build_for_statement, case_condition,
4 eval_assign_statement, eval_expr, eval_variable, expand_connect, expand_connect_const,
5 function_call, get_return_str, switch_condition, tb_method_call, try_infer_decl_type,
6 try_infer_var_assign,
7};
8use crate::conv::{Context, Conv};
9use crate::ir::{
10 self, Comptime, IrResult, Shape, TypeKind, VarIndex, VarKind, VarPath, VarPathSelect, VarSelect,
11};
12use crate::namespace::DefineContext;
13use crate::symbol::{Affiliation, SymbolKind};
14use crate::symbol_table;
15use crate::{AnalyzerError, ir_error};
16use veryl_parser::token_range::TokenRange;
17use veryl_parser::veryl_grammar_trait::*;
18
19impl Conv<&StatementBlock> for ir::StatementBlock {
20 fn conv(context: &mut Context, value: &StatementBlock) -> IrResult<Self> {
21 let statements: Vec<_> = value.into();
22 let mut ret = vec![];
23 for s in statements {
24 let x: IrResult<ir::StatementBlock> = Conv::conv(context, s);
25 match x {
26 Ok(x) => {
27 ret.append(&mut x.0.into_iter().filter(|x| !x.is_null()).collect());
28 }
29 Err(e) => {
30 if !context.in_generic {
31 ret.push(ir::Statement::Unsupported(e.token));
32 }
33 }
34 }
35 }
36 Ok(ir::StatementBlock(ret))
37 }
38}
39
40impl Conv<&StatementBlockItem> for ir::StatementBlock {
41 fn conv(context: &mut Context, value: &StatementBlockItem) -> IrResult<Self> {
42 match value {
43 StatementBlockItem::VarDeclaration(x) => {
44 let _: ir::Declaration = Conv::conv(context, x.var_declaration.as_ref())?;
45 Ok(ir::StatementBlock::default())
46 }
47 StatementBlockItem::LetStatement(x) => Conv::conv(context, x.let_statement.as_ref()),
48 StatementBlockItem::ConstDeclaration(x) => {
49 let _: ir::Declaration = Conv::conv(context, x.const_declaration.as_ref())?;
50 Ok(ir::StatementBlock::default())
51 }
52 StatementBlockItem::GenDeclaration(x) => {
53 let _: ir::Declaration = Conv::conv(context, x.gen_declaration.as_ref())?;
54 Ok(ir::StatementBlock::default())
55 }
56 StatementBlockItem::Statement(x) => Conv::conv(context, x.statement.as_ref()),
57 StatementBlockItem::ConcatenationAssignment(x) => {
58 Conv::conv(context, x.concatenation_assignment.as_ref())
59 }
60 }
61 }
62}
63
64impl Conv<&LetStatement> for ir::StatementBlock {
65 fn conv(context: &mut Context, value: &LetStatement) -> IrResult<Self> {
66 let define_context: DefineContext = (&value.r#let.let_token).into();
67 if !define_context.is_default() {
68 return Ok(ir::StatementBlock::default());
69 }
70
71 let token: TokenRange = value.into();
72
73 if let Ok(symbol) = symbol_table::resolve(value.identifier.as_ref())
74 && let SymbolKind::Variable(x) = &symbol.found.kind
75 {
76 let path = VarPath::new(symbol.found.token.text);
77 let kind = VarKind::Let;
78 let variable_token: TokenRange = (&value.identifier.identifier_token).into();
79
80 let inferred = try_infer_decl_type(
81 context,
82 &x.r#type,
83 &value.expression,
84 value.identifier.identifier_token.token.id,
85 token,
86 )?;
87 let r#type = if let Some((ref comptime, _)) = inferred {
88 comptime.r#type.clone()
89 } else {
90 x.r#type.to_ir_type(context, TypePosition::Variable)?
91 };
92 let clock_domain = x.clock_domain;
93
94 eval_variable(context, &path, kind, &r#type, clock_domain, variable_token);
95
96 let (id, comptime) = context.find_path(&path).ok_or_else(|| ir_error!(token))?;
97
98 let mut dst = ir::AssignDestination {
99 id,
100 path,
101 index: VarIndex::default(),
102 select: VarSelect::default(),
103 comptime,
104 token: variable_token,
105 };
106
107 let mut expr = if let Some(inferred) = inferred {
108 inferred
109 } else {
110 eval_expr(context, Some(r#type.clone()), &value.expression, false)?
111 };
112
113 let statements = eval_assign_statement(context, &mut dst, &mut expr, token)?;
114 Ok(ir::StatementBlock(statements))
115 } else {
116 Err(ir_error!(token))
117 }
118 }
119}
120
121impl Conv<&ConcatenationAssignment> for ir::StatementBlock {
122 fn conv(context: &mut Context, value: &ConcatenationAssignment) -> IrResult<Self> {
123 let token: TokenRange = value.into();
124
125 let items: Vec<_> = value.assign_concatenation_list.as_ref().into();
126
127 let mut dst = vec![];
128 for item in items {
129 let ident = item.hierarchical_identifier.as_ref();
130 let x: VarPathSelect = Conv::conv(context, ident)?;
131 if let Some(x) = x.to_assign_destination(context, false) {
132 dst.push(x);
133 } else {
134 if let Ok(symbol) = symbol_table::resolve(item.hierarchical_identifier.as_ref())
135 && let SymbolKind::Variable(x) = &symbol.found.kind
136 && x.affiliation == Affiliation::Module
137 {
138 let ident_token = ident.identifier.identifier_token.token;
139 context.insert_error(AnalyzerError::referring_before_definition(
140 &ident_token.text.to_string(),
141 &ident_token.into(),
142 ));
143 }
144 return Err(ir_error!(token));
145 }
146 }
147
148 let mut width = Some(0);
149 for x in &dst {
150 if let Some(x) = x.total_width(context)
151 && let Some(width) = &mut width
152 {
153 *width += x;
154 } else {
155 width = None;
156 }
157 }
158 if let Some(x) = width {
159 width = context.check_size(x, token);
160 }
161
162 let r#type = {
163 let mut t = ir::Type::new(TypeKind::Logic);
164 t.set_concrete_width(Shape::new(vec![width]));
165 t
166 };
167
168 let (_, expr) = eval_expr(context, Some(r#type), &value.expression, false)?;
169 let statement = ir::Statement::Assign(ir::AssignStatement {
170 dst,
171 width,
172 expr,
173 token,
174 });
175
176 Ok(ir::StatementBlock(vec![statement]))
177 }
178}
179
180impl Conv<&Statement> for ir::StatementBlock {
181 fn conv(context: &mut Context, value: &Statement) -> IrResult<Self> {
182 match value {
183 Statement::IdentifierStatement(x) => {
184 Conv::conv(context, x.identifier_statement.as_ref())
185 }
186 Statement::IfStatement(x) => Conv::conv(context, x.if_statement.as_ref()),
187 Statement::IfResetStatement(x) => Conv::conv(context, x.if_reset_statement.as_ref()),
188 Statement::ReturnStatement(x) => Ok(ir::StatementBlock(vec![Conv::conv(
189 context,
190 x.return_statement.as_ref(),
191 )?])),
192 Statement::BreakStatement(_) => Ok(ir::StatementBlock(vec![ir::Statement::Break])),
193 Statement::ForStatement(x) => Conv::conv(context, x.for_statement.as_ref()),
194 Statement::CaseStatement(x) => Conv::conv(context, x.case_statement.as_ref()),
195 Statement::SwitchStatement(x) => Conv::conv(context, x.switch_statement.as_ref()),
196 }
197 }
198}
199
200impl Conv<&IdentifierStatement> for ir::StatementBlock {
201 fn conv(context: &mut Context, value: &IdentifierStatement) -> IrResult<Self> {
202 let define_context: DefineContext = (&value.semicolon.semicolon_token).into();
203 if !define_context.is_default() {
204 return Ok(ir::StatementBlock::default());
205 }
206
207 let token: TokenRange = value.into();
208 let expr = value.expression_identifier.as_ref();
209
210 match value.identifier_statement_group.as_ref() {
211 IdentifierStatementGroup::Assignment(x) => {
212 match x.assignment.assignment_group.as_ref() {
213 AssignmentGroup::Equ(_) => {
214 let inferred = if let Ok(symbol) = symbol_table::resolve(expr) {
215 try_infer_var_assign(
216 context,
217 &symbol.found,
218 &x.assignment.expression,
219 token,
220 )?
221 } else {
222 None
223 };
224
225 let dst: VarPathSelect = Conv::conv(context, expr)?;
226
227 if let Some(mut dst) = dst.to_assign_destination(context, false) {
228 let mut expr = if let Some(inferred) = inferred {
229 inferred
230 } else {
231 eval_expr(
232 context,
233 Some(dst.comptime.r#type.clone()),
234 &x.assignment.expression,
235 false,
236 )?
237 };
238
239 let statements =
240 eval_assign_statement(context, &mut dst, &mut expr, token)?;
241 Ok(ir::StatementBlock(statements))
242 } else {
243 let _ = eval_expr(context, None, &x.assignment.expression, false)?;
245
246 Err(ir_error!(token))
247 }
248 }
249 AssignmentGroup::AssignmentOperator(op) => {
250 let op: ir::Op = Conv::conv(context, op.assignment_operator.as_ref())?;
251
252 let dst: VarPathSelect = Conv::conv(context, expr)?;
253 let src: VarPathSelect = Conv::conv(context, expr)?;
254
255 if let Some(dst) = dst.to_assign_destination(context, false)
256 && let Some(src) = src.to_expression(context)
257 {
258 let (_, expr) = eval_expr(
259 context,
260 Some(dst.comptime.r#type.clone()),
261 &x.assignment.expression,
262 false,
263 )?;
264
265 let width = dst.total_width(context);
266 let comptime = Box::new(Comptime::create_unknown(token));
267 let mut expr =
268 ir::Expression::Binary(Box::new(src), op, Box::new(expr), comptime);
269 let _ = expr.eval_comptime(context, width);
270
271 let statement = ir::AssignStatement {
272 dst: vec![dst],
273 width,
274 expr,
275 token,
276 };
277 let statement = ir::Statement::Assign(statement);
278 Ok(ir::StatementBlock(vec![statement]))
279 } else {
280 let _ = eval_expr(context, None, &x.assignment.expression, false)?;
282
283 Err(ir_error!(token))
284 }
285 }
286 AssignmentGroup::DiamondOperator(_) => {
287 let lhs: VarPathSelect = Conv::conv(context, expr)?;
288 let rhs: Vec<VarPathSelect> =
289 Conv::conv(context, x.assignment.expression.as_ref())?;
290
291 let (comptime, _) =
292 eval_expr(context, None, x.assignment.expression.as_ref(), false)?;
293
294 let statements = if comptime.is_const {
295 expand_connect_const(context, lhs, comptime, token)?
296 } else {
297 if rhs.len() != 1 {
298 context.insert_error(AnalyzerError::mismatch_type(
299 MismatchTypeKind::ConnectMultipleExpression,
300 &token,
301 ));
302 return Err(ir_error!(token));
303 }
304
305 let rhs = rhs[0].clone();
306
307 expand_connect(context, lhs, rhs, token)?
308 };
309
310 Ok(ir::StatementBlock(statements))
311 }
312 }
313 }
314 IdentifierStatementGroup::FunctionCall(x) => {
315 if let Some(tb_stmt) = tb_method_call(
317 context,
318 value.expression_identifier.as_ref(),
319 &x.function_call,
320 token,
321 )? {
322 return Ok(ir::StatementBlock(vec![tb_stmt]));
323 }
324
325 let args = if let Some(x) = &x.function_call.function_call_opt {
326 argument_list(context, x.argument_list.as_ref())?
327 } else {
328 ir::Arguments::Null
329 };
330
331 let resolved_path =
332 context.resolve_path(value.expression_identifier.as_ref().into());
333 let symbol = symbol_table::resolve(&resolved_path).map_err(|_| ir_error!(token))?;
334
335 match &symbol.found.kind {
336 SymbolKind::SystemFunction(_) => {
337 let name = symbol.found.token.text;
338 let args = args.to_system_function_args(context, &symbol.found);
339 let ret = ir::SystemFunctionCall::new(context, name, args, token)?;
340 Ok(ir::StatementBlock(vec![ir::Statement::SystemFunctionCall(
341 Box::new(ret),
342 )]))
343 }
344 SymbolKind::Function(x) => {
345 let ret = function_call(
346 context,
347 value.expression_identifier.as_ref(),
348 args,
349 token,
350 )?;
351
352 if x.ret.is_some() {
353 context.insert_error(AnalyzerError::unused_return(
354 &symbol.found.token.text.to_string(),
355 &token,
356 ));
357 }
358
359 Ok(ir::StatementBlock(vec![ir::Statement::FunctionCall(
360 Box::new(ret),
361 )]))
362 }
363 SymbolKind::ModportFunctionMember(x) => {
364 let symbol = symbol_table::get(x.function).unwrap();
365 if let SymbolKind::Function(x) = &symbol.kind {
366 let ret = function_call(
367 context,
368 value.expression_identifier.as_ref(),
369 args,
370 token,
371 )?;
372
373 if x.ret.is_some() {
374 context.insert_error(AnalyzerError::unused_return(
375 &symbol.token.text.to_string(),
376 &token,
377 ));
378 }
379
380 Ok(ir::StatementBlock(vec![ir::Statement::FunctionCall(
381 Box::new(ret),
382 )]))
383 } else {
384 unreachable!();
385 }
386 }
387 SymbolKind::ProtoFunction(_) | SymbolKind::SystemVerilog => {
388 Err(ir_error!(token))
389 }
390 _ => {
391 let name = symbol.found.token.text.to_string();
392 let kind = symbol.found.kind.to_kind_name();
393 context
394 .insert_error(AnalyzerError::call_non_function(&name, &kind, &token));
395 Err(ir_error!(token))
396 }
397 }
398 }
399 }
400 }
401}
402
403fn check_true_false(comptime: &Comptime) -> (bool, bool) {
404 if comptime.is_const
405 && let Ok(value) = comptime.get_value()
406 {
407 if value.to_usize().unwrap_or(0) != 0 {
408 (true, false)
409 } else {
410 (false, true)
411 }
412 } else {
413 (false, false)
414 }
415}
416
417impl Conv<&IfStatement> for ir::StatementBlock {
418 fn conv(context: &mut Context, value: &IfStatement) -> IrResult<Self> {
419 let define_context: DefineContext = (&value.r#if.if_token).into();
420 if !define_context.is_default() {
421 return Ok(ir::StatementBlock::default());
422 }
423
424 let (comptime, cond) = eval_expr(context, None, &value.expression, false)?;
425
426 if !comptime.r#type.is_binary() {
427 let token: TokenRange = value.expression.as_ref().into();
428 context.insert_error(AnalyzerError::invalid_logical_operand(false, &token));
429 }
430
431 let (true_side_only, false_side_only) = check_true_false(&comptime);
432
433 let true_side = if false_side_only {
434 vec![]
435 } else {
436 let true_side: ir::StatementBlock =
437 Conv::conv(context, value.statement_block.as_ref())?;
438 true_side.0
439 };
440
441 if true_side_only {
442 return Ok(ir::StatementBlock(true_side));
443 }
444
445 let mut false_side = vec![];
446 let mut else_if_break = false;
447
448 for x in &value.if_statement_list {
449 let (comptime, cond) = eval_expr(context, None, &x.expression, false)?;
450
451 if !comptime.r#type.is_binary() {
452 let token: TokenRange = x.expression.as_ref().into();
453 context.insert_error(AnalyzerError::invalid_logical_operand(false, &token));
454 }
455
456 let (true_side_only, false_side_only) = check_true_false(&comptime);
457
458 if false_side_only {
460 continue;
461 }
462
463 let true_side: ir::StatementBlock = Conv::conv(context, x.statement_block.as_ref())?;
464 let true_side = true_side.0;
465
466 let statement = ir::Statement::If(ir::IfStatement {
467 cond,
468 true_side,
469 false_side: vec![],
470 token: x.into(),
471 });
472
473 if let Some(x) = false_side.last_mut() {
474 if let ir::Statement::If(x) = x {
475 x.insert_leaf_false(vec![statement]);
476 }
477 } else {
478 false_side.push(statement);
479 }
480
481 if true_side_only {
483 else_if_break = true;
484 break;
485 }
486 }
487 if let Some(x) = &value.if_statement_opt
488 && !else_if_break
489 {
490 let block: ir::StatementBlock = Conv::conv(context, x.statement_block.as_ref())?;
491 let mut block = block.0;
492
493 if let Some(x) = false_side.last_mut() {
494 if let ir::Statement::If(x) = x {
495 x.insert_leaf_false(block);
496 }
497 } else {
498 false_side.append(&mut block);
499 }
500 }
501
502 if false_side_only {
503 Ok(ir::StatementBlock(false_side))
504 } else {
505 let statement = ir::Statement::If(ir::IfStatement {
506 cond,
507 true_side,
508 false_side,
509 token: value.into(),
510 });
511 Ok(ir::StatementBlock(vec![statement]))
512 }
513 }
514}
515
516impl Conv<&IfResetStatement> for ir::StatementBlock {
517 fn conv(context: &mut Context, value: &IfResetStatement) -> IrResult<Self> {
518 let define_context: DefineContext = (&value.if_reset.if_reset_token).into();
519 if !define_context.is_default() {
520 return Ok(ir::StatementBlock::default());
521 }
522
523 context.in_if_reset = true;
524
525 let true_side: ir::IrResult<ir::StatementBlock> =
526 context.block(|c| Conv::conv(c, value.statement_block.as_ref()));
527
528 context.in_if_reset = false;
529
530 let true_side = true_side?.0;
531
532 let mut false_side = vec![];
533 let mut else_if_break = false;
534
535 for x in &value.if_reset_statement_list {
536 let (comptime, cond) = eval_expr(context, None, &x.expression, false)?;
537
538 if !comptime.r#type.is_binary() {
539 let token: TokenRange = x.expression.as_ref().into();
540 context.insert_error(AnalyzerError::invalid_logical_operand(false, &token));
541 }
542
543 let (true_side_only, false_side_only) = check_true_false(&comptime);
544
545 if false_side_only {
547 continue;
548 }
549
550 let true_side: ir::StatementBlock = Conv::conv(context, x.statement_block.as_ref())?;
551 let true_side = true_side.0;
552
553 let statement = ir::Statement::If(ir::IfStatement {
554 cond,
555 true_side,
556 false_side: vec![],
557 token: x.into(),
558 });
559
560 if let Some(x) = false_side.last_mut() {
561 if let ir::Statement::If(x) = x {
562 x.insert_leaf_false(vec![statement]);
563 }
564 } else {
565 false_side.push(statement);
566 }
567
568 if true_side_only {
570 else_if_break = true;
571 break;
572 }
573 }
574 if let Some(x) = &value.if_reset_statement_opt
575 && !else_if_break
576 {
577 let block: ir::StatementBlock = Conv::conv(context, x.statement_block.as_ref())?;
578 let mut block = block.0;
579
580 if let Some(x) = false_side.last_mut() {
581 if let ir::Statement::If(x) = x {
582 x.insert_leaf_false(block);
583 }
584 } else {
585 false_side.append(&mut block);
586 }
587 }
588
589 let statement = ir::Statement::IfReset(ir::IfResetStatement {
590 true_side,
591 false_side,
592 token: value.into(),
593 });
594 Ok(ir::StatementBlock(vec![statement]))
595 }
596}
597
598impl Conv<&ReturnStatement> for ir::Statement {
599 fn conv(context: &mut Context, value: &ReturnStatement) -> IrResult<Self> {
600 let define_context: DefineContext = (&value.semicolon.semicolon_token).into();
601 if !define_context.is_default() {
602 return Ok(ir::Statement::Null);
603 }
604
605 let token: TokenRange = value.into();
606
607 let dst = VarPath::new(get_return_str());
608 let dst = VarPathSelect(dst, ir::VarSelect::default(), token);
609
610 if let Some(dst) = dst.to_assign_destination(context, false) {
611 let width = dst.total_width(context);
612 let (_, expr) = eval_expr(
613 context,
614 Some(dst.comptime.r#type.clone()),
615 &value.expression,
616 false,
617 )?;
618 Ok(ir::Statement::Assign(ir::AssignStatement {
619 dst: vec![dst],
620 width,
621 expr,
622 token,
623 }))
624 } else {
625 Err(ir_error!(token))
626 }
627 }
628}
629
630impl Conv<&ForStatement> for ir::StatementBlock {
631 fn conv(context: &mut Context, value: &ForStatement) -> IrResult<Self> {
632 let define_context: DefineContext = (&value.r#for.for_token).into();
633 if !define_context.is_default() {
634 return Ok(ir::StatementBlock::default());
635 }
636
637 let token: TokenRange = (&value.identifier.identifier_token).into();
638
639 let Ok(symbol) = symbol_table::resolve(value.identifier.as_ref()) else {
640 return Err(ir_error!(token));
641 };
642
643 let SymbolKind::Variable(ref x) = symbol.found.kind else {
644 unreachable!();
645 };
646 let r#type = x.r#type.to_ir_type(context, TypePosition::Variable)?;
647 let clock_domain = x.clock_domain;
648
649 let rev = value.for_statement_opt.is_some();
650
651 let step = value
652 .for_statement_opt0
653 .as_ref()
654 .map(|x| (x.assignment_operator.as_ref(), x.expression.as_ref()));
655
656 let for_range = build_for_range(context, &value.range, rev, step)?;
657
658 if !context.in_test_module
660 && let Some(range) = for_range.eval_iter(context)
661 {
662 return unroll_for(context, value, &r#type, clock_domain, &range, token);
663 }
664
665 build_for_statement(context, value, &r#type, clock_domain, for_range, token)
666 }
667}
668
669fn unroll_for(
670 context: &mut Context,
671 value: &ForStatement,
672 r#type: &ir::Type,
673 clock_domain: crate::symbol::ClockDomain,
674 range: &[usize],
675 token: TokenRange,
676) -> ir::IrResult<ir::StatementBlock> {
677 use veryl_parser::resource_table;
678
679 let mut ret = ir::StatementBlock::default();
680 'outer: for &i in range {
681 let label = format!("[{}]", i);
682 let label = resource_table::insert_str(&label);
683
684 context.push_hierarchy(label);
685
686 let block = context.block(|c| {
687 let index = value.identifier.text();
688 let path = ir::VarPath::new(index);
689 let kind = ir::VarKind::Const;
690 let mut comptime = ir::Comptime::from_type(r#type.clone(), clock_domain, token);
691 comptime.is_const = true;
692 if let Some(total_width) = r#type.total_width() {
693 comptime.value = ir::ValueVariant::Numeric(crate::value::Value::new(
694 i as u64,
695 total_width,
696 r#type.signed,
697 ));
698 }
699
700 let id = c.insert_var_path(path.clone(), comptime.clone());
701 let array_limit = c.config.evaluate_array_limit;
702 let variable = ir::Variable::new(
703 id,
704 path,
705 kind,
706 comptime.r#type.clone(),
707 vec![comptime.get_value().unwrap().clone()],
708 c.get_affiliation(),
709 &token,
710 array_limit,
711 );
712 c.insert_variable(id, variable);
713
714 let block: ir::IrResult<ir::StatementBlock> =
715 Conv::conv(c, value.statement_block.as_ref());
716 block
717 });
718
719 context.pop_hierarchy();
720
721 if let Ok(mut block) = block {
722 for stmt in block.0.drain(..) {
723 if matches!(stmt, ir::Statement::Break) {
724 break 'outer;
725 }
726 ret.0.push(stmt);
727 }
728 }
729 }
730 Ok(ret)
731}
732
733impl Conv<&CaseStatement> for ir::StatementBlock {
734 fn conv(context: &mut Context, value: &CaseStatement) -> IrResult<Self> {
735 let define_context: DefineContext = (&value.case.case_token).into();
736 if !define_context.is_default() {
737 return Ok(ir::StatementBlock::default());
738 }
739
740 let mut tgt: ir::Expression = Conv::conv(context, value.expression.as_ref())?;
741 tgt.eval_comptime(context, None);
742 let mut ret = ir::StatementBlock::default();
743
744 for item in &value.case_statement_list {
745 let cond = match item.case_item.case_item_group.as_ref() {
746 CaseItemGroup::CaseCondition(x) => {
747 Some(case_condition(context, &tgt, x.case_condition.as_ref())?)
748 }
749 CaseItemGroup::Defaul(_) => None,
750 };
751 let true_side: ir::StatementBlock = match item.case_item.case_item_group0.as_ref() {
752 CaseItemGroup0::Statement(x) => Conv::conv(context, x.statement.as_ref())?,
753 CaseItemGroup0::StatementBlock(x) => {
754 Conv::conv(context, x.statement_block.as_ref())?
755 }
756 };
757
758 let statements = if let Some(cond) = cond {
759 ir::StatementBlock(vec![ir::Statement::If(ir::IfStatement {
760 cond,
761 true_side: true_side.0,
762 false_side: vec![],
763 token: item.case_item.as_ref().into(),
764 })])
765 } else {
766 true_side
767 };
768
769 if ret.0.is_empty() {
770 ret = statements;
771 } else if let ir::Statement::If(x) = &mut ret.0[0] {
772 x.insert_leaf_false(statements.0);
773 }
774 }
775
776 Ok(ret)
777 }
778}
779
780impl Conv<&SwitchStatement> for ir::StatementBlock {
781 fn conv(context: &mut Context, value: &SwitchStatement) -> IrResult<Self> {
782 let define_context: DefineContext = (&value.switch.switch_token).into();
783 if !define_context.is_default() {
784 return Ok(ir::StatementBlock::default());
785 }
786
787 let mut ret = ir::StatementBlock::default();
788
789 for item in &value.switch_statement_list {
790 let cond = match item.switch_item.switch_item_group.as_ref() {
791 SwitchItemGroup::SwitchCondition(x) => {
792 Some(switch_condition(context, x.switch_condition.as_ref())?)
793 }
794 SwitchItemGroup::Defaul(_) => None,
795 };
796 let true_side: ir::StatementBlock = match item.switch_item.switch_item_group0.as_ref() {
797 SwitchItemGroup0::Statement(x) => Conv::conv(context, x.statement.as_ref())?,
798 SwitchItemGroup0::StatementBlock(x) => {
799 Conv::conv(context, x.statement_block.as_ref())?
800 }
801 };
802
803 let statements = if let Some(cond) = cond {
804 ir::StatementBlock(vec![ir::Statement::If(ir::IfStatement {
805 cond,
806 true_side: true_side.0,
807 false_side: vec![],
808 token: item.switch_item.as_ref().into(),
809 })])
810 } else {
811 true_side
812 };
813
814 if ret.0.is_empty() {
815 ret = statements;
816 } else if let ir::Statement::If(x) = &mut ret.0[0] {
817 x.insert_leaf_false(statements.0);
818 }
819 }
820
821 Ok(ret)
822 }
823}