feat(ir, parser): Support if/while/break/logical expr/cmp in parser and ir generator
This commit is contained in:
+89
-15
@@ -3,15 +3,32 @@ use std::fmt::Display;
|
||||
use crate::ast::types::Type as AstType;
|
||||
use crate::ast::types::BinaryOp as AstBinaryOp;
|
||||
use crate::ir::err::IRError;
|
||||
|
||||
pub enum VariableOrIntLit {
|
||||
Var(Variable),
|
||||
IntLit(i32),
|
||||
}
|
||||
|
||||
impl Display for VariableOrIntLit {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
VariableOrIntLit::Var(v) => write!(f, "{}", v),
|
||||
VariableOrIntLit::IntLit(i) => write!(f, "{}", i),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub enum IRInstr {
|
||||
Declare(Variable),
|
||||
DefineFunc(Function, Vec<Variable>, Vec<IRInstr>),
|
||||
Entry,
|
||||
Binary(Variable, Variable, BinaryOp, Variable),
|
||||
Cmp(Variable, VariableOrIntLit, CmpOp, VariableOrIntLit),
|
||||
Unary(Variable, UnaryOp, Variable),
|
||||
Exit(Option<Variable>),
|
||||
FuncCall(Function, Vec<Variable>, Option<Variable>),
|
||||
// Goto,
|
||||
// Label,
|
||||
Goto(usize),
|
||||
CondGoto(Variable, usize, usize), // condition, true label, false label
|
||||
Label(usize),
|
||||
Move(Variable, MoveRValue),
|
||||
}
|
||||
|
||||
@@ -20,6 +37,7 @@ impl Display for IRInstr {
|
||||
match self {
|
||||
IRInstr::Entry => write!(f, "entry"),
|
||||
IRInstr::Binary(dest, left, op, right) => write!(f, "{} = {} {},{}", dest, op, left, right),
|
||||
IRInstr::Cmp(dest, left, op, right) => write!(f, "{} = icmp {} {},{}", dest, op, left, right),
|
||||
IRInstr::Exit(v) => if let Some(v) = v { write!(f, "exit {}", v) } else { write!(f, "exit") },
|
||||
IRInstr::FuncCall(func, args, dest) => {
|
||||
if let Some(dest) = dest {
|
||||
@@ -33,7 +51,11 @@ impl Display for IRInstr {
|
||||
IRInstr::DefineFunc(func, args, body) => {
|
||||
let body_str = body.iter().map(|instr| format!(" {}", instr)).collect::<Vec<_>>().join("\n");
|
||||
write!(f, "define {} {{\n{}\n}}", func.to_decl_string(args), body_str)
|
||||
}
|
||||
},
|
||||
IRInstr::Goto(label) => write!(f, "br label .L{}", label),
|
||||
IRInstr::CondGoto(cond, true_label, false_label) => write!(f, "bc {}, .L{}, .L{}", cond, true_label, false_label),
|
||||
IRInstr::Label(label) => write!(f, ".L{}:", label),
|
||||
IRInstr::Unary(dest, op, src) => write!(f, "{} = {} {}", dest, op, src),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +73,16 @@ impl IRType {
|
||||
IRType::Void => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_elevate_result(lhs: IRType, rhs: IRType) -> Option<IRType> {
|
||||
if lhs == rhs {
|
||||
Some(lhs)
|
||||
} else if (lhs == IRType::I32 && rhs == IRType::I1) || (lhs == IRType::I1 && rhs == IRType::I32) {
|
||||
Some(IRType::I32)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Display for IRType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
@@ -153,6 +185,8 @@ pub enum BinaryOp {
|
||||
Mul,
|
||||
Div,
|
||||
Mod,
|
||||
}
|
||||
pub enum CmpOp {
|
||||
Le,
|
||||
Lt,
|
||||
Gt,
|
||||
@@ -160,6 +194,9 @@ pub enum BinaryOp {
|
||||
Ne,
|
||||
Eq,
|
||||
}
|
||||
pub enum UnaryOp {
|
||||
Neg
|
||||
}
|
||||
|
||||
impl Display for BinaryOp {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
@@ -169,12 +206,35 @@ impl Display for BinaryOp {
|
||||
BinaryOp::Mul => "mul",
|
||||
BinaryOp::Div => "div",
|
||||
BinaryOp::Mod => "mod",
|
||||
BinaryOp::Le => "le",
|
||||
BinaryOp::Lt => "lt",
|
||||
BinaryOp::Gt => "gt",
|
||||
BinaryOp::Ge => "ge",
|
||||
BinaryOp::Ne => "ne",
|
||||
BinaryOp::Eq => "eq",
|
||||
// BinaryOp::Le => "cmp le",
|
||||
// BinaryOp::Lt => "cmp lt",
|
||||
// BinaryOp::Gt => "cmp gt",
|
||||
// BinaryOp::Ge => "cmp ge",
|
||||
// BinaryOp::Ne => "cmp ne",
|
||||
// BinaryOp::Eq => "cmp eq",
|
||||
};
|
||||
write!(f, "{}", op_str)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for CmpOp {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let op_str = match self {
|
||||
CmpOp::Le => "le",
|
||||
CmpOp::Lt => "lt",
|
||||
CmpOp::Gt => "gt",
|
||||
CmpOp::Ge => "ge",
|
||||
CmpOp::Ne => "ne",
|
||||
CmpOp::Eq => "eq",
|
||||
};
|
||||
write!(f, "{}", op_str)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for UnaryOp {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let op_str = match self {
|
||||
UnaryOp::Neg => "neg",
|
||||
};
|
||||
write!(f, "{}", op_str)
|
||||
}
|
||||
@@ -187,12 +247,26 @@ impl From<AstBinaryOp> for BinaryOp {
|
||||
AstBinaryOp::Mul => BinaryOp::Mul,
|
||||
AstBinaryOp::Div => BinaryOp::Div,
|
||||
AstBinaryOp::Mod => BinaryOp::Mod,
|
||||
AstBinaryOp::Equal => BinaryOp::Eq,
|
||||
AstBinaryOp::NotEqual => BinaryOp::Ne,
|
||||
AstBinaryOp::Less => BinaryOp::Lt,
|
||||
AstBinaryOp::LessEqual => BinaryOp::Le,
|
||||
AstBinaryOp::Greater => BinaryOp::Gt,
|
||||
AstBinaryOp::GreaterEqual => BinaryOp::Ge,
|
||||
// AstBinaryOp::Equal => BinaryOp::Eq,
|
||||
// AstBinaryOp::NotEqual => BinaryOp::Ne,
|
||||
// AstBinaryOp::Less => BinaryOp::Lt,
|
||||
// AstBinaryOp::LessEqual => BinaryOp::Le,
|
||||
// AstBinaryOp::Greater => BinaryOp::Gt,
|
||||
// AstBinaryOp::GreaterEqual => BinaryOp::Ge,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<AstBinaryOp> for CmpOp {
|
||||
fn from(ast_op: AstBinaryOp) -> Self {
|
||||
match ast_op {
|
||||
AstBinaryOp::Equal => CmpOp::Eq,
|
||||
AstBinaryOp::NotEqual => CmpOp::Ne,
|
||||
AstBinaryOp::Less => CmpOp::Lt,
|
||||
AstBinaryOp::LessEqual => CmpOp::Le,
|
||||
AstBinaryOp::Greater => CmpOp::Gt,
|
||||
AstBinaryOp::GreaterEqual => CmpOp::Ge,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user