use super::*;
#[test]
fn test_create_for_loop_statement() {
let init = HirStatement::VariableDeclaration {
name: "i".to_string(),
var_type: HirType::Int,
initializer: Some(HirExpression::IntLiteral(0)),
};
let condition = HirExpression::BinaryOp {
op: BinaryOperator::LessThan,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(10)),
};
let increment = HirStatement::Assignment {
target: "i".to_string(),
value: HirExpression::BinaryOp {
op: BinaryOperator::Add,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(1)),
},
};
let body = vec![HirStatement::Assignment {
target: "sum".to_string(),
value: HirExpression::BinaryOp {
op: BinaryOperator::Add,
left: Box::new(HirExpression::Variable("sum".to_string())),
right: Box::new(HirExpression::Variable("i".to_string())),
},
}];
let for_loop = HirStatement::For {
init: vec![init],
condition: Some(condition),
increment: vec![increment],
body,
};
match for_loop {
HirStatement::For { init, condition, increment, body } => {
assert!(!init.is_empty());
assert!(!increment.is_empty());
assert_eq!(body.len(), 1);
let condition = condition.expect("should have condition");
assert!(matches!(condition, HirExpression::BinaryOp { .. }));
}
_ => panic!("Expected For statement"),
}
}
#[test]
fn test_for_loop_without_init() {
let condition = HirExpression::BinaryOp {
op: BinaryOperator::LessThan,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(10)),
};
let increment = HirStatement::Assignment {
target: "i".to_string(),
value: HirExpression::BinaryOp {
op: BinaryOperator::Add,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(1)),
},
};
let for_loop = HirStatement::For {
init: vec![],
condition: Some(condition),
increment: vec![increment],
body: vec![],
};
match for_loop {
HirStatement::For { init, .. } => {
assert!(init.is_empty());
}
_ => panic!("Expected For statement"),
}
}
#[test]
fn test_for_loop_without_increment() {
let init = HirStatement::VariableDeclaration {
name: "i".to_string(),
var_type: HirType::Int,
initializer: Some(HirExpression::IntLiteral(0)),
};
let condition = HirExpression::BinaryOp {
op: BinaryOperator::LessThan,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(10)),
};
let body = vec![HirStatement::Assignment {
target: "i".to_string(),
value: HirExpression::BinaryOp {
op: BinaryOperator::Add,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(1)),
},
}];
let for_loop =
HirStatement::For { init: vec![init], condition: Some(condition), increment: vec![], body };
match for_loop {
HirStatement::For { increment, .. } => {
assert!(increment.is_empty());
}
_ => panic!("Expected For statement"),
}
}
#[test]
fn test_for_loop_infinite() {
let for_loop = HirStatement::For {
init: vec![],
condition: Some(HirExpression::IntLiteral(1)), increment: vec![],
body: vec![HirStatement::Break],
};
match for_loop {
HirStatement::For { init, increment, body, .. } => {
assert!(init.is_empty());
assert!(increment.is_empty());
assert_eq!(body.len(), 1);
}
_ => panic!("Expected For statement"),
}
}
#[test]
fn test_for_loop_no_condition() {
let for_loop = HirStatement::For {
init: vec![],
condition: None,
increment: vec![],
body: vec![HirStatement::Break],
};
match for_loop {
HirStatement::For { condition, body, .. } => {
assert!(condition.is_none(), "for(;;) should have None condition");
assert_eq!(body.len(), 1);
}
_ => panic!("Expected For statement"),
}
}
#[test]
fn test_nested_for_loops() {
let inner_loop = HirStatement::For {
init: vec![HirStatement::VariableDeclaration {
name: "j".to_string(),
var_type: HirType::Int,
initializer: Some(HirExpression::IntLiteral(0)),
}],
condition: Some(HirExpression::BinaryOp {
op: BinaryOperator::LessThan,
left: Box::new(HirExpression::Variable("j".to_string())),
right: Box::new(HirExpression::IntLiteral(10)),
}),
increment: vec![HirStatement::Assignment {
target: "j".to_string(),
value: HirExpression::BinaryOp {
op: BinaryOperator::Add,
left: Box::new(HirExpression::Variable("j".to_string())),
right: Box::new(HirExpression::IntLiteral(1)),
},
}],
body: vec![],
};
let outer_loop = HirStatement::For {
init: vec![HirStatement::VariableDeclaration {
name: "i".to_string(),
var_type: HirType::Int,
initializer: Some(HirExpression::IntLiteral(0)),
}],
condition: Some(HirExpression::BinaryOp {
op: BinaryOperator::LessThan,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(10)),
}),
increment: vec![HirStatement::Assignment {
target: "i".to_string(),
value: HirExpression::BinaryOp {
op: BinaryOperator::Add,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(1)),
},
}],
body: vec![inner_loop],
};
match outer_loop {
HirStatement::For { body, .. } => {
assert_eq!(body.len(), 1);
assert!(matches!(body[0], HirStatement::For { .. }));
}
_ => panic!("Expected For statement"),
}
}
#[test]
fn test_for_loop_with_break_continue() {
let for_loop = HirStatement::For {
init: vec![HirStatement::VariableDeclaration {
name: "i".to_string(),
var_type: HirType::Int,
initializer: Some(HirExpression::IntLiteral(0)),
}],
condition: Some(HirExpression::BinaryOp {
op: BinaryOperator::LessThan,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(10)),
}),
increment: vec![HirStatement::Assignment {
target: "i".to_string(),
value: HirExpression::BinaryOp {
op: BinaryOperator::Add,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(1)),
},
}],
body: vec![
HirStatement::If {
condition: HirExpression::BinaryOp {
op: BinaryOperator::Equal,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(5)),
},
then_block: vec![HirStatement::Break],
else_block: None,
},
HirStatement::If {
condition: HirExpression::BinaryOp {
op: BinaryOperator::Equal,
left: Box::new(HirExpression::BinaryOp {
op: BinaryOperator::Modulo,
left: Box::new(HirExpression::Variable("i".to_string())),
right: Box::new(HirExpression::IntLiteral(2)),
}),
right: Box::new(HirExpression::IntLiteral(0)),
},
then_block: vec![HirStatement::Continue],
else_block: None,
},
],
};
match for_loop {
HirStatement::For { body, .. } => {
assert_eq!(body.len(), 2);
}
_ => panic!("Expected For statement"),
}
}