use rucc_base::Symbol;
use rucc_diag::Span;
use crate::asm::AsmId;
use crate::ast::{AttrList, DeclList, DerivedList, InitDeclaratorList, ParamList, StrId};
use crate::expr::ExprId;
use crate::init::InitId;
use crate::spec::{DeclSpecsId, Quals};
use crate::stmt::StmtId;
pub const MAX_DECLARATOR_DEPTH: usize = 200;
pub type DeclId = rucc_base::Idx<Decl>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Decl {
Error,
Var {
specs: DeclSpecsId,
declarators: InitDeclaratorList,
},
Function {
specs: DeclSpecsId,
declarator: DeclaratorId,
params: DeclList,
body: StmtId,
},
StaticAssert {
cond: ExprId,
message: Option<StrId>,
},
Asm(AsmId),
Attributes(AttrList),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct InitDeclarator {
pub declarator: DeclaratorId,
pub init: Option<InitId>,
pub asm_label: Option<StrId>,
pub attrs: AttrList,
pub span: Span,
}
pub type DeclaratorId = rucc_base::Idx<Declarator>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Declarator {
pub name: Option<Symbol>,
pub name_span: Span,
pub derived: DerivedList,
pub span: Span,
}
impl Declarator {
#[must_use]
pub const fn is_abstract(&self) -> bool {
self.name.is_none()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Derived {
Pointer {
quals: Quals,
attrs: AttrList,
},
Array {
size: ArraySize,
quals: Quals,
has_static: bool,
},
Function {
params: ParamList,
variadic: bool,
kind: ParamKind,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArraySize {
Unspecified,
Star,
Expr(ExprId),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ParamKind {
Prototype,
Void,
Empty,
Identifiers,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Param {
pub specs: Option<DeclSpecsId>,
pub declarator: DeclaratorId,
pub attrs: AttrList,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Member {
Field(Field),
StaticAssert {
cond: ExprId,
message: Option<StrId>,
span: Span,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Field {
pub specs: DeclSpecsId,
pub declarator: Option<DeclaratorId>,
pub bits: Option<ExprId>,
pub attrs: AttrList,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Enumerator {
pub name: Symbol,
pub value: Option<ExprId>,
pub attrs: AttrList,
pub span: Span,
}
pub type TypeNameId = rucc_base::Idx<TypeName>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TypeName {
pub specs: DeclSpecsId,
pub declarator: DeclaratorId,
pub span: Span,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_declaration_is_twenty_four_bytes() {
assert_eq!(size_of::<Decl>(), 24);
}
#[test]
fn a_declaration_id_is_four_bytes_even_when_optional() {
assert_eq!(size_of::<DeclId>(), 4);
assert_eq!(size_of::<Option<DeclId>>(), 4);
}
#[test]
fn a_declarator_with_no_name_is_abstract() {
let d = Declarator {
name: None,
name_span: Span::DUMMY,
derived: DerivedList::EMPTY,
span: Span::DUMMY,
};
assert!(d.is_abstract());
}
}