1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#![deny(missing_docs)]
use std::collections::{HashMap, HashSet};
use crate::common::errors::*;
use crate::common::score::Result;
use crate::common::source::Spanned;
use crate::common::Verbosity;
use crate::score::{Def, ResolvableName, ScopeRef, ScoreContext};
#[derive(Clone, Debug)]
pub struct Scope {
pub parent: Option<ScopeRef>,
pub defs: HashMap<ResolvableName, Vec<Spanned<Def>>>,
pub imported_defs: HashMap<ResolvableName, Vec<Spanned<Def>>>,
pub imported_scopes: HashSet<ScopeRef>,
}
impl Scope {
pub fn new(parent: Option<ScopeRef>) -> Scope {
Scope {
parent: parent,
defs: HashMap::new(),
imported_defs: HashMap::new(),
imported_scopes: HashSet::new(),
}
}
}
impl<'lazy, 'sb, 'ast, 'ctx> ScoreContext<'lazy, 'sb, 'ast, 'ctx> {
pub fn with_scope<F, R>(&self, scope: ScopeRef, f: F) -> Result<R>
where
F: FnOnce(&mut Scope) -> Result<R>,
{
let mut tbl = self.sb.scope2_table.borrow_mut();
let scp = match tbl.get_mut(&scope) {
Some(s) => s,
None => {
self.emit(DiagBuilder2::bug(format!(
"scope {:?} does not exist`",
scope
)));
return Err(());
}
};
f(scp)
}
pub fn subscope(&self, scope: ScopeRef, parent: ScopeRef) {
self.sb
.scope2_table
.borrow_mut()
.insert(scope, Scope::new(Some(parent)));
}
pub fn define(&self, scope: ScopeRef, name: Spanned<ResolvableName>, def: Def) -> Result<()> {
if self.sess.opts.verbosity.contains(Verbosity::NAMES) {
debugln!("define `{}` as {:?} in scope {:?}", name.value, def, scope);
}
self.with_scope(scope, |scope| match def {
Def::Enum(_) => {
scope
.defs
.entry(name.value)
.or_insert_with(|| Vec::new())
.push(Spanned::new(def, name.span));
Ok(())
}
_ => {
let ins = scope
.defs
.insert(name.value, vec![Spanned::new(def, name.span)]);
if let Some(existing) = ins {
self.emit(
DiagBuilder2::error(format!("`{}` has already been declared", name.value))
.span(name.span)
.add_note("Previous declaration was here:")
.span(existing.last().unwrap().span),
);
Err(())
} else {
Ok(())
}
}
})
}
pub fn import_def(
&self,
scope: ScopeRef,
name: Spanned<ResolvableName>,
def: Def,
) -> Result<()> {
self.with_scope(scope, |scope| {
scope
.imported_defs
.entry(name.value)
.or_insert_with(|| Vec::new())
.push(Spanned::new(def, name.span));
Ok(())
})
}
pub fn import_scope(&self, scope: ScopeRef, into: ScopeRef) -> Result<()> {
self.with_scope(into, |into| {
into.imported_scopes.insert(scope);
Ok(())
})
}
}