bitsy_lang/
package.rs

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/// A Package is a parsed Bitsy file.
14/// It consists of a number of top-level [`Item`]s.
15#[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    /// Look at all components in scope, work out their type, and build a [`context::Context`] to assist in typechecking.
109    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/// A top-level declaration in a [`Package`].
178#[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/// [`Wire`]s drive the value of port, node, or register.
246#[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        // TODO REMOVE THIS.
255        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}