Add 'and' and 'or' operators to IR Generator
This commit is contained in:
parent
b3a8188dfe
commit
52d7ebde15
2 changed files with 69 additions and 3 deletions
|
@ -90,7 +90,7 @@ impl fmt::Display for IrInstructionType {
|
||||||
IrInstructionType::CondJump(cond, then_dest, else_dest) => {
|
IrInstructionType::CondJump(cond, then_dest, else_dest) => {
|
||||||
format!("CondJump({cond}, {then_dest}, {else_dest})")
|
format!("CondJump({cond}, {then_dest}, {else_dest})")
|
||||||
}
|
}
|
||||||
IrInstructionType::Label(name) => format!("Label({name})"),
|
IrInstructionType::Label(name) => format!("\nLabel({name})"),
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "{}", string)
|
write!(f, "{}", string)
|
||||||
|
|
|
@ -126,8 +126,74 @@ fn visit_ast_node<'source>(
|
||||||
}
|
}
|
||||||
BinaryOp(left, op, right) => match *op {
|
BinaryOp(left, op, right) => match *op {
|
||||||
"=" => todo!(),
|
"=" => todo!(),
|
||||||
"and" => todo!(),
|
"and" => {
|
||||||
"or" => todo!(),
|
let l_right = add_label("and_right", right.loc, labels);
|
||||||
|
let l_skip = add_label("and_skip", ast.loc, labels);
|
||||||
|
let l_end = add_label("and_end", ast.loc, labels);
|
||||||
|
|
||||||
|
let left_var = visit_ast_node(left, types, symbols, instructions, labels);
|
||||||
|
instructions.push(IrInstruction::new(
|
||||||
|
left.loc,
|
||||||
|
CondJump(
|
||||||
|
left_var,
|
||||||
|
Box::new(l_right.clone()),
|
||||||
|
Box::new(l_skip.clone()),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
instructions.push(l_right);
|
||||||
|
let right_var = visit_ast_node(right, types, symbols, instructions, labels);
|
||||||
|
let result_var = add_var(&ast.node_type, types);
|
||||||
|
instructions.push(IrInstruction::new(
|
||||||
|
right.loc,
|
||||||
|
Copy(right_var, result_var.clone()),
|
||||||
|
));
|
||||||
|
instructions.push(IrInstruction::new(right.loc, Jump(Box::new(l_end.clone()))));
|
||||||
|
|
||||||
|
instructions.push(l_skip);
|
||||||
|
instructions.push(IrInstruction::new(
|
||||||
|
right.loc,
|
||||||
|
LoadBoolConst(false, result_var.clone()),
|
||||||
|
));
|
||||||
|
instructions.push(IrInstruction::new(right.loc, Jump(Box::new(l_end.clone()))));
|
||||||
|
|
||||||
|
instructions.push(l_end);
|
||||||
|
result_var
|
||||||
|
}
|
||||||
|
"or" => {
|
||||||
|
let l_right = add_label("or_right", right.loc, labels);
|
||||||
|
let l_skip = add_label("or_skip", ast.loc, labels);
|
||||||
|
let l_end = add_label("or_end", ast.loc, labels);
|
||||||
|
|
||||||
|
let left_var = visit_ast_node(left, types, symbols, instructions, labels);
|
||||||
|
instructions.push(IrInstruction::new(
|
||||||
|
left.loc,
|
||||||
|
CondJump(
|
||||||
|
left_var,
|
||||||
|
Box::new(l_skip.clone()),
|
||||||
|
Box::new(l_right.clone()),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
instructions.push(l_right);
|
||||||
|
let right_var = visit_ast_node(right, types, symbols, instructions, labels);
|
||||||
|
let result_var = add_var(&ast.node_type, types);
|
||||||
|
instructions.push(IrInstruction::new(
|
||||||
|
right.loc,
|
||||||
|
Copy(right_var, result_var.clone()),
|
||||||
|
));
|
||||||
|
instructions.push(IrInstruction::new(right.loc, Jump(Box::new(l_end.clone()))));
|
||||||
|
|
||||||
|
instructions.push(l_skip);
|
||||||
|
instructions.push(IrInstruction::new(
|
||||||
|
right.loc,
|
||||||
|
LoadBoolConst(true, result_var.clone()),
|
||||||
|
));
|
||||||
|
instructions.push(IrInstruction::new(right.loc, Jump(Box::new(l_end.clone()))));
|
||||||
|
|
||||||
|
instructions.push(l_end);
|
||||||
|
result_var
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let op_var = symbols.get(op).clone();
|
let op_var = symbols.get(op).clone();
|
||||||
let left_var = visit_ast_node(left, types, symbols, instructions, labels);
|
let left_var = visit_ast_node(left, types, symbols, instructions, labels);
|
||||||
|
|
Reference in a new issue