galvan_resolver/
scope.rs

1use crate::{Lookup, LookupContext};
2use galvan_ast::{
3    DeclModifier, FnDecl, Ident, Ownership, ToplevelItem, TypeDecl, TypeElement, TypeIdent,
4};
5use std::collections::HashMap;
6
7#[derive(Debug, Default)]
8pub struct Scope<'a> {
9    pub parent: Option<&'a Scope<'a>>,
10    pub variables: HashMap<Ident, Variable>,
11
12    lookup: Option<LookupContext<'a>>,
13}
14
15impl Scope<'_> {
16    pub fn child(parent: &Self) -> Scope {
17        Scope {
18            parent: Some(parent),
19            variables: HashMap::new(),
20            lookup: None,
21        }
22    }
23
24    pub fn declare_variable(&mut self, variable: Variable) {
25        self.variables.insert(variable.ident.clone(), variable);
26    }
27
28    pub fn get_variable(&self, ident: &Ident) -> Option<&Variable> {
29        self.variables
30            .get(ident)
31            .or_else(|| self.parent.and_then(|parent| parent.get_variable(ident)))
32    }
33}
34
35impl<'a> Scope<'a> {
36    pub fn set_lookup(&mut self, lookup: LookupContext<'a>) {
37        self.lookup = Some(lookup);
38    }
39}
40
41impl Lookup for Scope<'_> {
42    fn resolve_type(&self, name: &TypeIdent) -> Option<&ToplevelItem<TypeDecl>> {
43        self.lookup
44            .as_ref()
45            .and_then(|lookup| lookup.resolve_type(name))
46            .or_else(|| self.parent.and_then(|parent| parent.resolve_type(name)))
47    }
48
49    fn resolve_function(
50        &self,
51        receiver: Option<&TypeIdent>,
52        name: &Ident,
53        labels: &[&str],
54    ) -> Option<&ToplevelItem<FnDecl>> {
55        self.lookup
56            .as_ref()
57            .and_then(|lookup| lookup.resolve_function(receiver, name, labels))
58            .or_else(|| {
59                self.parent
60                    .and_then(|parent| parent.resolve_function(receiver, name, labels))
61            })
62    }
63}
64
65#[derive(Clone, Debug)]
66pub struct Variable {
67    pub ident: Ident,
68    pub modifier: DeclModifier,
69    /// If the variable type cannot be identified, this is `None` and type inference will be delegated to Rust
70    pub ty: Option<TypeElement>,
71    pub ownership: Ownership,
72}
73
74impl Variable {
75    pub fn is_mut(&self) -> bool {
76        matches!(self.modifier, DeclModifier::Mut(_))
77    }
78}