tiger_lib/
variable_scopes.rs1use scc::HashMap as SccHashMap;
2
3use crate::report::{ErrorKey, warn};
4use crate::scopes::Scopes;
5use crate::token::Token;
6
7#[derive(Debug)]
10pub struct VariableScopes {
11 namespace: &'static str,
13 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}