1use crate::dcatomic::DCAtomicField;
24use crate::dcfield::ClassField;
25use crate::dcfile::DCFile;
26use crate::dconfig::*;
27use crate::globals;
28use crate::hashgen::*;
29use multimap::MultiMap;
30
31pub type FieldName2Field<'dc> = MultiMap<String, &'dc ClassField<'dc>>;
32pub type FieldId2Field<'dc> = MultiMap<globals::FieldId, &'dc ClassField<'dc>>;
33
34#[derive(Debug, Clone)]
39pub struct DClass<'dc> {
40 dcfile: &'dc DCFile<'dc>,
41 class_name: String,
42 class_id: globals::DClassId,
43 is_bogus_class: bool,
44 class_parents: Vec<&'dc DClass<'dc>>,
45 constructor: Option<&'dc DCAtomicField<'dc>>,
46 fields: Vec<&'dc ClassField<'dc>>,
47 inherited_fields: Vec<&'dc ClassField<'dc>>,
48 field_name_2_field: FieldName2Field<'dc>,
49 field_id_2_field: FieldId2Field<'dc>,
50}
51
52impl std::fmt::Display for DClass<'_> {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 write!(f, "dclass ")?;
55 f.write_str(&self.get_name())?;
56
57 if !self.class_parents.is_empty() {
58 write!(f, " : ")?;
59
60 for (i, parent) in self.class_parents.iter().enumerate() {
61 parent.fmt(f)?;
62
63 if i != self.class_parents.len() - 1 {
64 write!(f, ", ")?;
65 }
66 }
67 }
68 write!(f, " {{ // index ")?;
69 self.class_id.fmt(f)?;
70 writeln!(f)?;
71
72 if let Some(constructor) = self.constructor {
73 constructor.fmt(f)?;
74 }
75
76 for field in &self.fields {
77 match field {
78 ClassField::Atomic(cf) => cf.fmt(f)?,
79 ClassField::Field(cf) => cf.fmt(f)?,
80 ClassField::Molecular(cf) => cf.fmt(f)?,
81 }
82 }
83 writeln!(f, "}};")
84 }
85}
86
87impl DCFileConfigAccessor for DClass<'_> {
88 fn get_dc_config(&self) -> &DCFileConfig {
89 self.dcfile.get_dc_config()
90 }
91}
92
93impl LegacyDCHash for DClass<'_> {
94 fn generate_hash(&self, hashgen: &mut DCHashGenerator) {
95 hashgen.add_string(self.get_name());
96 hashgen.add_int(self.get_num_parents().try_into().unwrap());
97
98 for parent in &self.class_parents {
99 {
100 hashgen.add_int(i32::from(parent.get_dclass_id()));
101 }
102
103 if let Some(constructor) = &self.constructor {
104 constructor.generate_hash(hashgen);
105 }
106 }
107 hashgen.add_int(self.fields.len().try_into().unwrap());
108
109 for field in &self.fields {
110 match field {
111 ClassField::Field(field) => field.generate_hash(hashgen),
112 ClassField::Atomic(atomic) => atomic.generate_hash(hashgen),
113 ClassField::Molecular(molecular) => molecular.generate_hash(hashgen),
114 }
115 }
116 }
117}
118
119impl<'dc> DClass<'dc> {
120 pub fn get_field_by_name(&self, name: &str) -> Option<&'dc ClassField> {
121 match self.field_name_2_field.get(name) {
122 Some(pointer) => Some(pointer),
123 None => None,
124 }
125 }
126
127 #[inline(always)]
128 pub fn get_name(&self) -> String {
129 self.class_name.clone()
130 }
131
132 #[inline(always)]
133 pub fn get_dclass_id(&self) -> globals::DClassId {
134 self.class_id
135 }
136
137 #[inline(always)]
138 pub fn get_num_parents(&self) -> usize {
139 self.class_parents.len()
140 }
141
142 #[inline(always)]
143 pub fn get_parent(&self, index: usize) -> Option<&'static DClass> {
144 self.class_parents.get(index).cloned()
146 }
147
148 #[inline(always)]
149 pub fn has_constructor(&self) -> bool {
150 self.constructor.is_some()
151 }
152
153 #[inline(always)]
154 pub fn get_constructor(&self) -> Option<&'dc DCAtomicField> {
155 if let Some(atomic) = &self.constructor {
156 Some(atomic)
157 } else {
158 None
159 }
160 }
161}
162
163pub(crate) mod interim {
166 use crate::globals;
167 use crate::parser::ast;
168 use crate::parser::lexer::Span;
169 use std::cell::RefCell;
170 use std::rc::Rc;
171
172 #[derive(Debug)]
173 pub struct DClass {
174 pub span: Span,
175 pub identifier: String,
176 pub parents: Vec<String>,
177 pub fields: ast::ClassFields,
178 pub class_id: globals::DClassId,
179 pub is_bogus_class: bool,
180 pub class_parents: Vec<Rc<RefCell<DClass>>>,
181 }
182
183 impl DClass {
184 #[inline(always)]
185 pub fn add_parent(&mut self, parent: Rc<RefCell<DClass>>) {
186 self.class_parents.push(parent);
187 }
188
189 pub fn add_class_field(&mut self, field: ast::AtomicOrMolecular) {
194 self.is_bogus_class = false;
195 self.fields.push(field);
196 }
197 }
198}