petr_bind/
impls.rs

1use petr_ast::{Commented, Expression, ExpressionWithBindings, FunctionDeclaration, ImportStatement, TypeDeclaration};
2use petr_utils::{Identifier, SpannedItem};
3
4use crate::{binder::ScopeKind, Bind, Binder, Item};
5
6impl Bind for SpannedItem<&TypeDeclaration> {
7    type Output = Option<(Identifier, Item)>;
8
9    fn bind(
10        &self,
11        binder: &mut Binder,
12    ) -> Self::Output {
13        binder.insert_type(self)
14    }
15}
16
17impl Bind for SpannedItem<TypeDeclaration> {
18    type Output = Option<(Identifier, Item)>;
19
20    fn bind(
21        &self,
22        binder: &mut Binder,
23    ) -> Self::Output {
24        binder.insert_type(&self.span().with_item(self.item()))
25    }
26}
27
28impl Bind for Expression {
29    // the scope that the expression lives in
30    type Output = ();
31
32    fn bind(
33        &self,
34        binder: &mut Binder,
35    ) -> Self::Output {
36        // only lists get their own scope for now
37        match self {
38            Expression::List(list) => {
39                list.bind(binder);
40            },
41            Expression::Binding(ExpressionWithBindings {
42                bindings,
43                expression,
44                expr_id,
45            }) => binder.with_scope(ScopeKind::ExpressionWithBindings, |binder, scope_id| {
46                for binding in bindings.iter() {
47                    let binding_id = binder.insert_binding(binding.clone());
48                    binder.insert_into_current_scope(binding.name.id, binding.name.span().with_item(Item::Binding(binding_id)));
49                }
50                expression.bind(binder);
51                binder.insert_expression(*expr_id, scope_id);
52            }),
53            _ => (),
54        }
55    }
56}
57
58impl Bind for petr_ast::List {
59    type Output = ();
60
61    fn bind(
62        &self,
63        binder: &mut Binder,
64    ) -> Self::Output {
65        for item in self.elements.iter() {
66            item.bind(binder);
67        }
68    }
69}
70
71impl<T: Bind> Bind for Commented<T> {
72    type Output = T::Output;
73
74    fn bind(
75        &self,
76        binder: &mut Binder,
77    ) -> Self::Output {
78        self.item().bind(binder)
79    }
80}
81
82impl<T: Bind> Bind for SpannedItem<T> {
83    type Output = T::Output;
84
85    fn bind(
86        &self,
87        binder: &mut Binder,
88    ) -> Self::Output {
89        self.item().bind(binder)
90    }
91}
92
93impl Bind for SpannedItem<FunctionDeclaration> {
94    type Output = Option<(Identifier, Item)>;
95
96    fn bind(
97        &self,
98        binder: &mut Binder,
99    ) -> Self::Output {
100        binder.insert_function(&self.span().with_item(self.item()))
101    }
102}
103
104impl Bind for SpannedItem<&FunctionDeclaration> {
105    type Output = Option<(Identifier, Item)>;
106
107    fn bind(
108        &self,
109        binder: &mut Binder,
110    ) -> Self::Output {
111        binder.insert_function(self)
112    }
113}
114
115impl Bind for ImportStatement {
116    type Output = Option<(Identifier, Item)>;
117
118    fn bind(
119        &self,
120        binder: &mut Binder,
121    ) -> Self::Output {
122        let item = Item::Import {
123            path:  self.path.clone(),
124            alias: self.alias,
125        };
126
127        // the alias, if any, or the last path element if there is no alias
128        let name = self.alias.unwrap_or_else(|| *self.path.iter().last().expect("should never be empty"));
129
130        binder.insert_into_current_scope(name.id, name.span.with_item(item.clone()));
131
132        if self.is_exported() {
133            Some((name, item))
134        } else {
135            None
136        }
137    }
138}