suicmez/src/c_ir.rs
2025-12-16 01:49:49 +05:30

157 lines
3.7 KiB
Rust

#[derive(Debug, Clone)]
pub enum CType {
Void,
Int,
Float,
Bool,
Char,
Ptr(Box<CType>),
Struct(String),
UnnamedStruct(Vec<CVarDecl>),
Array(Box<CType>, usize), // type and size
Func(Vec<CType>, Box<CType>), // args and return
}
impl CType {
pub fn to_string(&self) -> String {
match self {
CType::Void => "void".to_string(),
CType::Int => "int".to_string(),
CType::Float => "float".to_string(),
CType::Bool => "bool".to_string(),
CType::Char => "char".to_string(),
CType::Ptr(inner) => format!("{}*", inner.to_string()),
CType::Struct(name) => format!("struct {}", name),
CType::UnnamedStruct(fields) => {
let field_strs: Vec<String> = fields
.iter()
.map(|f| format!(" {} {};", f.ty.to_string(), f.name))
.collect();
format!("struct {{\n{}\n}}", field_strs.join("\n"))
}
CType::Array(inner, size) => format!("{}[{}]", inner.to_string(), size),
CType::Func(args, ret) => {
let arg_strs: Vec<String> = args.iter().map(|t| t.to_string()).collect();
format!("{} (*)({})", ret.to_string(), arg_strs.join(", "))
}
}
}
}
#[derive(Debug, Clone)]
pub struct CVarDecl {
pub name: String,
pub ty: CType,
pub initializer: Option<CExpr>,
}
#[derive(Debug, Clone)]
pub struct CStructDecl {
pub name: String,
pub fields: Vec<CVarDecl>,
}
#[derive(Debug, Clone)]
pub struct CFuncDecl {
pub name: String,
pub return_type: CType,
pub params: Vec<CVarDecl>,
pub body: Option<Vec<CStmt>>,
}
#[derive(Debug, Clone)]
pub enum CExpr {
IntLit(i64),
FloatLit(f64),
BoolLit(bool),
StringLit(String),
Var(String),
Call(String, Vec<CExpr>),
BinOp(Box<CExpr>, CBinaryOp, Box<CExpr>),
UnOp(CUnaryOp, Box<CExpr>),
Cast(Box<CExpr>, CType),
StructLit(String, Vec<(String, CExpr)>),
EnumLit(String, String, Vec<CExpr>), // enum_name, variant_name, args
ArrayLit(Vec<CExpr>),
Index(Box<CExpr>, Box<CExpr>),
Dot(Box<CExpr>, String),
AddrOf(Box<CExpr>),
Deref(Box<CExpr>),
}
#[derive(Debug, Clone)]
pub enum CBinaryOp {
Add,
Sub,
Mul,
Div,
Mod,
Eq,
Neq,
Lt,
Gt,
Leq,
Geq,
And,
Or,
}
impl CBinaryOp {
pub fn to_string(&self) -> &'static str {
match self {
CBinaryOp::Add => "+",
CBinaryOp::Sub => "-",
CBinaryOp::Mul => "*",
CBinaryOp::Div => "/",
CBinaryOp::Mod => "%",
CBinaryOp::Eq => "==",
CBinaryOp::Neq => "!=",
CBinaryOp::Lt => "<",
CBinaryOp::Gt => ">",
CBinaryOp::Leq => "<=",
CBinaryOp::Geq => ">=",
CBinaryOp::And => "&&",
CBinaryOp::Or => "||",
}
}
}
#[derive(Debug, Clone)]
pub enum CUnaryOp {
Neg,
Not,
Ref,
Deref,
}
impl CUnaryOp {
pub fn to_string(&self) -> &'static str {
match self {
CUnaryOp::Neg => "-",
CUnaryOp::Not => "!",
CUnaryOp::Ref => "&",
CUnaryOp::Deref => "*",
}
}
}
#[derive(Debug, Clone)]
pub enum CStmt {
VarDecl(CVarDecl),
Expr(CExpr),
Assign(CExpr, CExpr),
If(CExpr, Vec<CStmt>, Option<Vec<CStmt>>),
While(CExpr, Vec<CStmt>),
For(CVarDecl, CExpr, CExpr, Vec<CStmt>), // init, cond, incr, body
Return(Option<CExpr>),
Break,
Continue,
Block(Vec<CStmt>),
}
#[derive(Debug, Clone)]
pub enum CToplevel {
StructDecl(CStructDecl),
FuncDecl(CFuncDecl),
VarDecl(CVarDecl),
}