1use super::*;
2mod resolve;
3
4use once_cell::sync::OnceCell;
5
6use std::collections::BTreeMap;
7use std::sync::Arc;
8
9pub use ast::WireType;
10
11pub type Name = String;
12
13#[derive(Debug, Clone)]
16pub struct Package {
17 items: Vec<Item>,
18}
19
20impl Package {
21 pub fn from(ast: &ast::Package) -> Result<Package, Vec<BitsyError>> {
22 let items = resolve::resolve(ast);
23 let package = Package {
24 items,
25 };
26 package.check()?;
27 Ok(package)
28 }
29
30 pub fn top(&self, top_name: &str) -> Result<Circuit, BitsyError> {
31 if let Some(top) = self.moddef(top_name) {
32 Ok(Circuit(self.clone(), top))
33 } else {
34 Err(BitsyError::Unknown(None, format!("No such mod definition: {top_name}")))
35 }
36 }
37
38 pub fn moddefs(&self) -> Vec<Arc<Component>> {
39 let mut results = vec![];
40 for items in &self.items {
41 if let Item::ModDef(moddef) = &items {
42 results.push(moddef.clone());
43 } else if let Item::ExtDef(moddef) = &items {
44 results.push(moddef.clone());
45 }
46 }
47 results
48 }
49
50 pub fn moddef(&self, name: &str) -> Option<Arc<Component>> {
51 for item in &self.items {
52 if let Item::ModDef(moddef) = &item {
53 if moddef.name() == name {
54 return Some(moddef.clone());
55 }
56 } else if let Item::ExtDef(moddef) = &item {
57 if moddef.name() == name {
58 return Some(moddef.clone());
59 }
60 }
61 }
62 None
63 }
64
65 pub fn extdef(&self, name: &str) -> Option<Arc<Component>> {
66 for item in &self.items {
67 if let Item::ExtDef(extdef) = &item {
68 if extdef.name() == name {
69 return Some(extdef.clone());
70 }
71 }
72 }
73 None
74 }
75
76 pub fn typedef(&self, name: &str) -> Option<Arc<EnumTypeDef>> {
77 for item in &self.items {
78 if let Item::EnumTypeDef(typedef) = &item {
79 if typedef.name == name {
80 return Some(typedef.clone());
81 }
82 }
83 }
84 None
85 }
86
87 pub fn fndef(&self, name: &str) -> Option<Arc<FnDef>> {
88 for item in &self.items {
89 if let Item::FnDef(fndef) = &item {
90 if fndef.name == name {
91 return Some(fndef.clone());
92 }
93 }
94 }
95 None
96 }
97
98 pub fn fndefs(&self) -> Vec<Arc<FnDef>> {
99 let mut result = vec![];
100 for item in &self.items {
101 if let Item::FnDef(fndef) = &item {
102 result.push(fndef.clone());
103 }
104 }
105 result
106 }
107
108 pub fn context_for(&self, component: Arc<Component>) -> Context<Path, Type> {
110 let mut ctx = vec![];
111 for (path, target) in self.visible_paths(component.clone()) {
112 let typ = self.type_of(target).unwrap();
113 ctx.push((path, typ));
114 }
115 Context::from(ctx)
116 }
117
118 pub(crate) fn visible_paths(&self, component: Arc<Component>) -> Vec<(Path, Arc<Component>)> {
119 let mut results = vec![];
120 for child in component.children() {
121 match &*child {
122 Component::Node(_loc, name, _typ) => results.push((name.to_string().into(), child.clone())),
123 Component::Incoming(_loc, name, _typ) => results.push((name.to_string().into(), child.clone())),
124 Component::Outgoing(_loc, name, _typ) => results.push((name.to_string().into(), child.clone())),
125 Component::Reg(_loc, name, _typ, _reset) => results.push((name.to_string().into(), child.clone())),
126 Component::Mod(_loc, name, _children, _wires, _whens) => {
127 let mod_path: Path = name.to_string().into();
128 for (path, component) in child.port_paths() {
129 results.push((mod_path.join(path), component.clone()));
130 }
131 },
132 Component::ModInst(_loc, name, moddef) => {
133 let mod_path: Path = name.to_string().into();
134 for (path, component) in moddef.port_paths() {
135 results.push((mod_path.join(path), component.clone()));
136 }
137 },
138 Component::Ext(_loc, name, _children) => {
139 let ext_path: Path = name.to_string().into();
140 for (path, component) in child.port_paths() {
141 results.push((ext_path.join(path), component.clone()));
142 }
143 },
144 }
145 }
146 results
147 }
148
149 pub fn type_of(&self, component: Arc<Component>) -> Option<Type> {
150 match &*component {
151 Component::Mod(_loc, _name, _children, _wires, _whens) => None,
152 Component::ModInst(_loc, _name, _defname) => None,
153 Component::Ext(_loc, _name, _children) => None,
154 Component::Node(_loc, _name, typ) => Some(typ.clone()),
155 Component::Outgoing(_loc, _name, typ) => Some(typ.clone()),
156 Component::Incoming(_loc, _name, typ) => Some(typ.clone()),
157 Component::Reg(_loc, _name, typ, _reset) => Some(typ.clone()),
158 }
159 }
160
161 pub(crate) fn component_from(&self, component: Arc<Component>, path: Path) -> Option<Arc<Component>> {
162 let mut result: Arc<Component> = component;
163 for part in path.split(".") {
164 if let Some(child) = result.child(part) {
165 if let Component::ModInst(_loc, _name, moddef) = &*child {
166 result = moddef.clone();
167 } else {
168 result = child.clone();
169 }
170 }
171 }
172 Some(result)
173 }
174
175}
176
177#[derive(Debug, Clone)]
179pub enum Item {
180 ModDef(Arc<Component>),
181 ExtDef(Arc<Component>),
182 EnumTypeDef(Arc<EnumTypeDef>),
183 StructTypeDef(Arc<StructTypeDef>),
184 FnDef(Arc<FnDef>),
185}
186
187impl Item {
188 pub fn name(&self) -> &str {
189 match self {
190 Item::ModDef(component) => component.name(),
191 Item::ExtDef(component) => component.name(),
192 Item::EnumTypeDef(typedef) => &typedef.name,
193 Item::StructTypeDef(typedef) => &typedef.name,
194 Item::FnDef(typedef) => &typedef.name,
195 }
196 }
197
198 pub fn is_moddef(&self) -> bool {
199 match self {
200 Item::ModDef(_component) => true,
201 Item::ExtDef(_component) => true,
202 _ => false,
203 }
204 }
205
206 pub fn is_typedef(&self) -> bool {
207 match self {
208 Item::EnumTypeDef(_typedef) => true,
209 Item::StructTypeDef(_typedef) => true,
210 _ => false,
211 }
212 }
213
214 pub fn is_fndef(&self) -> bool {
215 match self {
216 Item::FnDef(_fndef) => true,
217 _ => false,
218 }
219 }
220
221 pub fn as_type(&self) -> Option<Type> {
222 match self {
223 Item::EnumTypeDef(typedef) => Some(Type::Enum(typedef.clone())),
224 Item::StructTypeDef(typedef) => Some(Type::Struct(typedef.clone())),
225 _ => None,
226 }
227 }
228
229 pub fn as_component(&self) -> Option<Arc<Component>> {
230 match self {
231 Item::ModDef(component) => Some(component.clone()),
232 Item::ExtDef(component) => Some(component.clone()),
233 _ => None,
234 }
235 }
236
237 pub fn as_fndef(&self) -> Option<Arc<FnDef>> {
238 match self {
239 Item::FnDef(fndef) => Some(fndef.clone()),
240 _ => None,
241 }
242 }
243}
244
245#[derive(Debug, Clone)]
247pub struct Wire(pub Loc, pub Path, pub Arc<Expr>, pub WireType);
248
249#[derive(Debug, Clone)]
250pub struct When(pub Arc<Expr>, pub Vec<Wire>);
251
252impl Wire {
253 pub fn new(loc: Loc, target: Path, expr: Arc<Expr>, typ: WireType) -> Wire {
254 Wire(loc, target, expr, typ)
256 }
257}
258
259impl HasLoc for Wire {
260 fn loc(&self) -> Loc {
261 let Wire(loc, _target, _expr, _wire_type) = self;
262 loc.clone()
263 }
264}
265
266impl HasLoc for Component {
267 fn loc(&self) -> Loc {
268 match self {
269 Component::Mod(loc, _name, _children, _wires, _whens) => loc.clone(),
270 Component::ModInst(loc, _name, _moddef) => loc.clone(),
271 Component::Ext(loc, _name, _children) => loc.clone(),
272 Component::Incoming(loc, _name, _typ) => loc.clone(),
273 Component::Outgoing(loc, _name, _typ) => loc.clone(),
274 Component::Node(loc, _name, _typ) => loc.clone(),
275 Component::Reg(loc, _name, _typ, _expr) => loc.clone(),
276 }
277 }
278}