tiger_lib/
variable_scopes.rs

1use scc::HashMap as SccHashMap;
2
3use crate::report::{ErrorKey, warn};
4use crate::scopes::Scopes;
5use crate::token::Token;
6
7/// A registry of what is known about the scope types of variables.
8/// There will be one registry per namespace (globals, global lists, variables, variable lists).
9#[derive(Debug)]
10pub struct VariableScopes {
11    /// The string to be used when reporting scope conflicts to the user.
12    namespace: &'static str,
13    /// The registry. It is a hashmap that allows concurrent access and has internal mutability.
14    /// The values are the scope types, and a bool that is true if the scope was overridden in
15    /// configuration or false if the scope was deduced.
16    scopes: SccHashMap<&'static str, (Scopes, bool)>,
17}
18
19impl VariableScopes {
20    pub fn new(namespace: &'static str) -> Self {
21        Self { namespace, scopes: SccHashMap::default() }
22    }
23
24    #[allow(dead_code)]
25    pub fn config_override(&self, name: &'static str, scopes: Scopes) {
26        self.scopes.upsert_sync(name, (scopes, true));
27    }
28
29    pub fn scopes(&self, name: &str) -> Scopes {
30        self.scopes.read_sync(name, |_, (s, _)| *s).unwrap_or(Scopes::all())
31    }
32
33    pub fn expect(&self, name: &'static str, token: &Token, scopes: Scopes) {
34        self.scopes
35            .entry_sync(name)
36            .and_modify(|(s, overridden)| {
37                if s.intersects(scopes) {
38                    if !*overridden {
39                        *s &= scopes;
40                    }
41                } else {
42                    let verb = if *overridden { "configured" } else { "deduced" };
43                    let msg = format!(
44                        "{}{name} was {verb} to be {s} but scope seems to be {scopes}",
45                        self.namespace
46                    );
47                    warn(ErrorKey::Scopes).weak().msg(msg).loc(token).push();
48                }
49            })
50            .or_insert((scopes, false));
51    }
52}