use rucc_ast::{BinaryOp, UnaryOp};
use rucc_base::{Idx, IdxRange};
use rucc_types::TypeId;
use crate::decl::DeclId;
use crate::stmt::StmtId;
use crate::tast::{ConstId, LabelId, StrId};
pub type ExprId = Idx<Expr>;
#[derive(Debug)]
pub struct ExprRef;
pub type ExprList = IdxRange<ExprRef>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Expr {
pub kind: ExprKind,
pub ty: TypeId,
pub category: Category,
}
impl Expr {
#[must_use]
pub const fn new(kind: ExprKind, ty: TypeId, category: Category) -> Expr {
Expr { kind, ty, category }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Category {
Rvalue,
Lvalue,
Bitfield,
Function,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExprKind {
Error,
Const(ConstId),
Str(StrId),
Decl(DeclId),
Member {
base: ExprId,
field: u32,
},
Subscript {
base: ExprId,
index: ExprId,
},
Call {
callee: ExprId,
args: ExprList,
},
Unary {
op: UnaryOp,
operand: ExprId,
},
Binary {
op: BinaryOp,
lhs: ExprId,
rhs: ExprId,
},
Assign {
op: Option<BinaryOp>,
computation: TypeId,
lhs: ExprId,
rhs: ExprId,
},
Cond {
cond: ExprId,
then: ExprId,
otherwise: ExprId,
},
Comma {
lhs: ExprId,
rhs: ExprId,
},
Cast(ExprId),
Convert {
kind: Conversion,
operand: ExprId,
},
CompoundLiteral(DeclId),
StmtExpr(StmtId),
LabelAddr(LabelId),
VaArg {
list: ExprId,
},
VaStart {
list: ExprId,
},
VaEnd {
list: ExprId,
},
VaCopy {
dst: ExprId,
src: ExprId,
},
Classify {
op: Classify,
lhs: ExprId,
rhs: Option<ExprId>,
},
Sign {
op: Sign,
lhs: ExprId,
rhs: Option<ExprId>,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Classify {
Unordered,
LessGreater,
Nan,
Infinite,
Finite,
SignBit,
}
impl Classify {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Classify::Unordered => "unordered",
Classify::LessGreater => "less-greater",
Classify::Nan => "nan",
Classify::Infinite => "infinite",
Classify::Finite => "finite",
Classify::SignBit => "signbit",
}
}
#[must_use]
pub const fn is_pair(self) -> bool {
matches!(self, Classify::Unordered | Classify::LessGreater)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Sign {
Clear,
Of,
}
impl Sign {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Sign::Clear => "clear",
Sign::Of => "of",
}
}
#[must_use]
pub const fn is_pair(self) -> bool {
matches!(self, Sign::Of)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Conversion {
Lvalue,
ArrayDecay,
FunctionDecay,
Arithmetic,
Pointer,
Bool,
NullPointer,
Void,
}
impl Conversion {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Conversion::Lvalue => "lvalue",
Conversion::ArrayDecay => "array-decay",
Conversion::FunctionDecay => "function-decay",
Conversion::Arithmetic => "arithmetic",
Conversion::Pointer => "pointer",
Conversion::Bool => "bool",
Conversion::NullPointer => "null-pointer",
Conversion::Void => "void",
}
}
}