use ir_lang::{BinOp, Builder, Function, Type, UnOp};
fn mismatched_operands() -> Function {
let mut b = Builder::new("mismatched_operands", &[Type::Int, Type::Bool], Type::Int);
let x = b.block_params(b.entry())[0];
let flag = b.block_params(b.entry())[1];
let bad = b.bin(BinOp::Add, x, flag);
b.ret(Some(bad));
b.finish()
}
fn not_on_an_int() -> Function {
let mut b = Builder::new("not_on_an_int", &[Type::Int], Type::Bool);
let x = b.block_params(b.entry())[0];
let bad = b.un(UnOp::Not, x);
b.ret(Some(bad));
b.finish()
}
fn non_boolean_condition() -> Function {
let mut b = Builder::new("non_boolean_condition", &[Type::Int], Type::Unit);
let x = b.block_params(b.entry())[0];
let yes = b.create_block(&[]);
let no = b.create_block(&[]);
b.branch(x, yes, &[], no, &[]);
b.switch_to(yes);
b.ret(None);
b.switch_to(no);
b.ret(None);
b.finish()
}
fn wrong_argument_count() -> Function {
let mut b = Builder::new("wrong_argument_count", &[], Type::Int);
let exit = b.create_block(&[Type::Int]);
b.jump(exit, &[]); b.switch_to(exit);
let r = b.block_params(exit)[0];
b.ret(Some(r));
b.finish()
}
fn unterminated_block() -> Function {
Builder::new("unterminated_block", &[], Type::Unit).finish()
}
fn main() {
let cases = [
mismatched_operands(),
not_on_an_int(),
non_boolean_condition(),
wrong_argument_count(),
unterminated_block(),
];
for func in &cases {
match func.validate() {
Ok(()) => println!("{:>22}: unexpectedly valid", func.name()),
Err(e) => println!("{:>22}: {e}", func.name()),
}
}
}