1
1
mirror of https://github.com/oxalica/nil.git synced 2024-10-27 12:30:52 +03:00

Flatten Bindings into Arena in Module

This commit is contained in:
oxalica 2022-08-09 03:29:36 +08:00
parent 61819663d8
commit 4b160fe412
3 changed files with 162 additions and 58 deletions

View File

@ -1,6 +1,6 @@
use super::{
AstPtr, Attrpath, BindingKey, BindingValue, Bindings, Expr, ExprId, Literal, Module,
ModuleSourceMap, NameDef, NameDefId, NameDefKind, Pat, Path, PathAnchor,
AstPtr, Attrpath, Binding, BindingId, BindingKey, BindingValue, Bindings, Expr, ExprId,
Literal, Module, ModuleSourceMap, NameDef, NameDefId, NameDefKind, Pat, Path, PathAnchor,
};
use crate::{Diagnostic, DiagnosticKind, FileId};
use indexmap::IndexMap;
@ -17,6 +17,7 @@ pub(super) fn lower(file_id: FileId, parse: Parse) -> (Module, ModuleSourceMap)
module: Module {
exprs: Arena::new(),
name_defs: Arena::new(),
bindings: Arena::new(),
// Placeholder.
entry_expr: ExprId::from_raw(0.into()),
diagnostics: Vec::new(),
@ -51,6 +52,10 @@ impl LowerCtx {
id
}
fn alloc_binding(&mut self, key: BindingKey, value: BindingValue) -> BindingId {
self.module.bindings.alloc(Binding { key, value })
}
fn diagnostic(&mut self, range: TextRange, kind: DiagnosticKind) {
self.module.diagnostics.push(Diagnostic { range, kind });
}
@ -521,7 +526,10 @@ impl MergingSet {
entries: self
.entries
.into_iter()
.map(|(k, v)| (k, v.finish(ctx)))
.map(|(k, v)| {
let v = v.finish(ctx);
ctx.alloc_binding(k, v)
})
.collect(),
inherit_froms: self.inherit_froms.into(),
}
@ -647,6 +655,12 @@ mod tests {
for (i, e) in module.exprs.iter() {
writeln!(got, "{}: {:?}", i.into_raw(), e).unwrap();
}
if !module.bindings.is_empty() {
writeln!(got).unwrap();
}
for (i, b) in module.bindings.iter() {
writeln!(got, "{}: {:?}", i.into_raw(), b).unwrap();
}
if !module.name_defs.is_empty() {
writeln!(got).unwrap();
}
@ -921,7 +935,12 @@ mod tests {
2: Literal(Int(2))
3: Literal(Int(3))
4: Literal(Int(4))
5: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(0))), (Dynamic(Idx::<Expr>(1)), Expr(Idx::<Expr>(2))), (Name("c"), Expr(Idx::<Expr>(3))), (Name("\n"), Expr(Idx::<Expr>(4)))], inherit_froms: [] })
5: Attrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1), Idx::<Binding>(2), Idx::<Binding>(3)], inherit_froms: [] })
0: Binding { key: Name("a"), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: Dynamic(Idx::<Expr>(1)), value: Expr(Idx::<Expr>(2)) }
2: Binding { key: Name("c"), value: Expr(Idx::<Expr>(3)) }
3: Binding { key: Name("\n"), value: Expr(Idx::<Expr>(4)) }
"#]],
);
}
@ -939,7 +958,13 @@ mod tests {
2: Reference("c")
3: Reference("d")
4: Reference("e")
5: Attrset(Bindings { entries: [(Name("a"), Inherit(Idx::<Expr>(0))), (Name("b"), Inherit(Idx::<Expr>(1))), (Name("c"), Inherit(Idx::<Expr>(2))), (Name("f"), InheritFrom(1)), (Name("g"), InheritFrom(1))], inherit_froms: [Idx::<Expr>(3), Idx::<Expr>(4)] })
5: Attrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1), Idx::<Binding>(2), Idx::<Binding>(3), Idx::<Binding>(4)], inherit_froms: [Idx::<Expr>(3), Idx::<Expr>(4)] })
0: Binding { key: Name("a"), value: Inherit(Idx::<Expr>(0)) }
1: Binding { key: Name("b"), value: Inherit(Idx::<Expr>(1)) }
2: Binding { key: Name("c"), value: Inherit(Idx::<Expr>(2)) }
3: Binding { key: Name("f"), value: InheritFrom(1) }
4: Binding { key: Name("g"), value: InheritFrom(1) }
"#]],
);
}
@ -952,8 +977,12 @@ mod tests {
expect![[r#"
0: Literal(Int(1))
1: Literal(Int(2))
2: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(0))), (Name("c"), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
2: Attrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
0: Binding { key: Name("b"), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: Name("c"), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("a"), value: Expr(Idx::<Expr>(2)) }
"#]],
);
// Path and attrset.
@ -962,8 +991,12 @@ mod tests {
expect![[r#"
0: Literal(Int(1))
1: Literal(Int(2))
2: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(0))), (Name("c"), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
2: Attrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
0: Binding { key: Name("b"), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: Name("c"), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("a"), value: Expr(Idx::<Expr>(2)) }
"#]],
);
// Attrset and path.
@ -972,8 +1005,12 @@ mod tests {
expect![[r#"
0: Literal(Int(1))
1: Literal(Int(2))
2: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(0))), (Name("c"), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
2: Attrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
0: Binding { key: Name("b"), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: Name("c"), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("a"), value: Expr(Idx::<Expr>(2)) }
"#]],
);
// Attrset and attrset.
@ -982,8 +1019,12 @@ mod tests {
expect![[r#"
0: Literal(Int(1))
1: Literal(Int(2))
2: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(0))), (Name("c"), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
2: Attrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
0: Binding { key: Name("b"), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: Name("c"), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("a"), value: Expr(Idx::<Expr>(2)) }
"#]],
);
}
@ -998,8 +1039,12 @@ mod tests {
0: Literal(Int(1))
1: Literal(Int(2))
2: RecAttrset(Bindings { entries: [(NameDef(Idx::<NameDef>(0)), Expr(Idx::<Expr>(0))), (NameDef(Idx::<NameDef>(1)), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
2: RecAttrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
0: Binding { key: NameDef(Idx::<NameDef>(0)), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: NameDef(Idx::<NameDef>(1)), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("a"), value: Expr(Idx::<Expr>(2)) }
0: NameDef { name: "b", kind: RecAttrset }
1: NameDef { name: "c", kind: RecAttrset }
@ -1014,8 +1059,12 @@ mod tests {
0: Literal(Int(1))
1: Literal(Int(2))
2: RecAttrset(Bindings { entries: [(NameDef(Idx::<NameDef>(0)), Expr(Idx::<Expr>(0))), (NameDef(Idx::<NameDef>(1)), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
2: RecAttrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
0: Binding { key: NameDef(Idx::<NameDef>(0)), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: NameDef(Idx::<NameDef>(1)), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("a"), value: Expr(Idx::<Expr>(2)) }
0: NameDef { name: "b", kind: RecAttrset }
1: NameDef { name: "c", kind: RecAttrset }
@ -1030,8 +1079,12 @@ mod tests {
0: Literal(Int(1))
1: Literal(Int(2))
2: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(0))), (Name("c"), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
2: Attrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
0: Binding { key: Name("b"), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: Name("c"), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("a"), value: Expr(Idx::<Expr>(2)) }
"#]],
);
@ -1043,8 +1096,12 @@ mod tests {
0: Literal(Int(1))
1: Literal(Int(2))
2: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(0))), (Name("c"), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
2: Attrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
0: Binding { key: Name("b"), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: Name("c"), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("a"), value: Expr(Idx::<Expr>(2)) }
"#]],
);
@ -1056,8 +1113,12 @@ mod tests {
0: Literal(Int(1))
1: Literal(Int(2))
2: RecAttrset(Bindings { entries: [(NameDef(Idx::<NameDef>(0)), Expr(Idx::<Expr>(0))), (NameDef(Idx::<NameDef>(1)), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
2: RecAttrset(Bindings { entries: [Idx::<Binding>(0), Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
0: Binding { key: NameDef(Idx::<NameDef>(0)), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: NameDef(Idx::<NameDef>(1)), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("a"), value: Expr(Idx::<Expr>(2)) }
0: NameDef { name: "b", kind: RecAttrset }
1: NameDef { name: "c", kind: RecAttrset }
@ -1071,8 +1132,11 @@ mod tests {
"rec { a.b = 1; }",
expect![[r#"
0: Literal(Int(1))
1: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(0)))], inherit_froms: [] })
2: RecAttrset(Bindings { entries: [(NameDef(Idx::<NameDef>(0)), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
1: Attrset(Bindings { entries: [Idx::<Binding>(0)], inherit_froms: [] })
2: RecAttrset(Bindings { entries: [Idx::<Binding>(1)], inherit_froms: [] })
0: Binding { key: Name("b"), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: NameDef(Idx::<NameDef>(0)), value: Expr(Idx::<Expr>(1)) }
0: NameDef { name: "a", kind: RecAttrset }
"#]],
@ -1086,9 +1150,13 @@ mod tests {
"{ a.b = rec { c = 1; }; }",
expect![[r#"
0: Literal(Int(1))
1: RecAttrset(Bindings { entries: [(NameDef(Idx::<NameDef>(0)), Expr(Idx::<Expr>(0)))], inherit_froms: [] })
2: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
1: RecAttrset(Bindings { entries: [Idx::<Binding>(0)], inherit_froms: [] })
2: Attrset(Bindings { entries: [Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
0: Binding { key: NameDef(Idx::<NameDef>(0)), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: Name("b"), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("a"), value: Expr(Idx::<Expr>(2)) }
0: NameDef { name: "c", kind: RecAttrset }
"#]],
@ -1103,10 +1171,15 @@ mod tests {
Diagnostic { range: 8..24, kind: LetAttrset }
0: Literal(Int(1))
1: Attrset(Bindings { entries: [(Name("d"), Expr(Idx::<Expr>(0)))], inherit_froms: [] })
2: LetAttrset(Bindings { entries: [(NameDef(Idx::<NameDef>(0)), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
3: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(2)))], inherit_froms: [] })
4: Attrset(Bindings { entries: [(Name("a"), Expr(Idx::<Expr>(3)))], inherit_froms: [] })
1: Attrset(Bindings { entries: [Idx::<Binding>(0)], inherit_froms: [] })
2: LetAttrset(Bindings { entries: [Idx::<Binding>(1)], inherit_froms: [] })
3: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
4: Attrset(Bindings { entries: [Idx::<Binding>(3)], inherit_froms: [] })
0: Binding { key: Name("d"), value: Expr(Idx::<Expr>(0)) }
1: Binding { key: NameDef(Idx::<NameDef>(0)), value: Expr(Idx::<Expr>(1)) }
2: Binding { key: Name("b"), value: Expr(Idx::<Expr>(2)) }
3: Binding { key: Name("a"), value: Expr(Idx::<Expr>(3)) }
0: NameDef { name: "c", kind: RecAttrset }
"#]],
@ -1122,9 +1195,14 @@ mod tests {
1: Literal(Int(1))
2: Reference("a")
3: Literal(Int(2))
4: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
5: Attrset(Bindings { entries: [(Name("b"), Expr(Idx::<Expr>(3)))], inherit_froms: [] })
6: Attrset(Bindings { entries: [(Dynamic(Idx::<Expr>(0)), Expr(Idx::<Expr>(4))), (Dynamic(Idx::<Expr>(2)), Expr(Idx::<Expr>(5)))], inherit_froms: [] })
4: Attrset(Bindings { entries: [Idx::<Binding>(0)], inherit_froms: [] })
5: Attrset(Bindings { entries: [Idx::<Binding>(2)], inherit_froms: [] })
6: Attrset(Bindings { entries: [Idx::<Binding>(1), Idx::<Binding>(3)], inherit_froms: [] })
0: Binding { key: Name("b"), value: Expr(Idx::<Expr>(1)) }
1: Binding { key: Dynamic(Idx::<Expr>(0)), value: Expr(Idx::<Expr>(4)) }
2: Binding { key: Name("b"), value: Expr(Idx::<Expr>(3)) }
3: Binding { key: Dynamic(Idx::<Expr>(2)), value: Expr(Idx::<Expr>(5)) }
"#]],
);
}
@ -1149,9 +1227,12 @@ mod tests {
expect![[r#"
0: Reference("a")
1: Literal(Int(1))
2: Attrset(Bindings { entries: [(Dynamic(Idx::<Expr>(0)), Expr(Idx::<Expr>(1)))], inherit_froms: [] })
2: Attrset(Bindings { entries: [Idx::<Binding>(0)], inherit_froms: [] })
3: Literal(Int(1))
4: LetIn(Bindings { entries: [(NameDef(Idx::<NameDef>(0)), Expr(Idx::<Expr>(2)))], inherit_froms: [] }, Idx::<Expr>(3))
4: LetIn(Bindings { entries: [Idx::<Binding>(1)], inherit_froms: [] }, Idx::<Expr>(3))
0: Binding { key: Dynamic(Idx::<Expr>(0)), value: Expr(Idx::<Expr>(1)) }
1: Binding { key: NameDef(Idx::<NameDef>(0)), value: Expr(Idx::<Expr>(2)) }
0: NameDef { name: "a", kind: LetIn }
"#]],

View File

@ -55,12 +55,14 @@ fn source_map(db: &dyn DefDatabase, file_id: FileId) -> Arc<ModuleSourceMap> {
pub struct Module {
exprs: Arena<Expr>,
name_defs: Arena<NameDef>,
bindings: Arena<Binding>,
entry_expr: ExprId,
diagnostics: Vec<Diagnostic>,
}
pub type ExprId = Idx<Expr>;
pub type NameDefId = Idx<NameDef>;
pub type BindingId = Idx<Binding>;
impl ops::Index<ExprId> for Module {
type Output = Expr;
@ -76,6 +78,13 @@ impl ops::Index<NameDefId> for Module {
}
}
impl ops::Index<BindingId> for Module {
type Output = Binding;
fn index(&self, index: BindingId) -> &Self::Output {
&self.bindings[index]
}
}
impl Module {
pub fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
@ -138,7 +147,7 @@ pub enum Expr {
}
impl Expr {
pub(crate) fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
pub(crate) fn walk_child_exprs(&self, module: &Module, mut f: impl FnMut(ExprId)) {
match self {
Self::Missing | Self::Reference(_) | Self::Literal(_) => {}
Self::Lambda(_, pat, body) => {
@ -175,11 +184,11 @@ impl Expr {
xs.iter().copied().for_each(f)
}
Self::LetIn(bindings, body) => {
bindings.walk_child_exprs(&mut f);
bindings.walk_child_exprs(module, &mut f);
f(*body);
}
Self::Attrset(bindings) | Self::RecAttrset(bindings) | Self::LetAttrset(bindings) => {
bindings.walk_child_exprs(f);
bindings.walk_child_exprs(module, f);
}
}
}
@ -239,10 +248,16 @@ pub type Attrpath = Box<[ExprId]>;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Bindings {
pub entries: Box<[(BindingKey, BindingValue)]>,
pub entries: Box<[BindingId]>,
pub inherit_froms: Box<[ExprId]>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Binding {
pub key: BindingKey,
pub value: BindingValue,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum BindingKey {
NameDef(NameDefId),
@ -258,19 +273,25 @@ pub enum BindingValue {
}
impl Bindings {
pub(crate) fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
for (key, kind) in self.entries.iter() {
match key {
BindingKey::NameDef(_) | BindingKey::Name(_) => {}
&BindingKey::Dynamic(expr) => f(expr),
}
match *kind {
BindingValue::Inherit(e) | BindingValue::Expr(e) => f(e),
BindingValue::InheritFrom(_) => {}
}
pub(crate) fn walk_child_exprs(&self, module: &Module, mut f: impl FnMut(ExprId)) {
for &binding in self.entries.iter() {
module[binding].walk_child_exprs(&mut f);
}
for &e in self.inherit_froms.iter() {
f(e);
}
}
}
impl Binding {
pub(crate) fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
match self.key {
BindingKey::NameDef(_) | BindingKey::Name(_) => {}
BindingKey::Dynamic(expr) => f(expr),
}
match self.value {
BindingValue::Inherit(e) | BindingValue::Expr(e) => f(e),
BindingValue::InheritFrom(_) => {}
}
}
}

View File

@ -124,7 +124,7 @@ impl ModuleScopes {
let scope = self.traverse_bindings(module, bindings, scope);
self.traverse_expr(module, *body, scope);
}
e => e.walk_child_exprs(|e| self.traverse_expr(module, e, scope)),
e => e.walk_child_exprs(module, |e| self.traverse_expr(module, e, scope)),
}
}
@ -136,13 +136,14 @@ impl ModuleScopes {
) -> ScopeId {
let mut defs = HashMap::default();
for (k, v) in bindings.entries.iter() {
if let &BindingKey::NameDef(def) = k {
for &binding in bindings.entries.iter() {
let binding = &module[binding];
if let &BindingKey::NameDef(def) = &binding.key {
defs.insert(module[def].name.clone(), def);
}
// Inherited attrs are resolved in the outer scope.
if let &BindingValue::Inherit(expr) = v {
if let BindingValue::Inherit(expr) = binding.value {
assert!(matches!(&module[expr], Expr::Reference(_)));
self.traverse_expr(module, expr, scope);
}
@ -157,11 +158,12 @@ impl ModuleScopes {
})
};
for (k, v) in bindings.entries.iter() {
if let &BindingKey::Dynamic(expr) = k {
for &binding in bindings.entries.iter() {
let binding = &module[binding];
if let BindingKey::Dynamic(expr) = binding.key {
self.traverse_expr(module, expr, scope);
}
if let &BindingValue::Expr(expr) = v {
if let BindingValue::Expr(expr) = binding.value {
self.traverse_expr(module, expr, scope);
}
}