-
Notifications
You must be signed in to change notification settings - Fork 225
/
Copy pathmodule_data.rs
186 lines (156 loc) · 5.52 KB
/
module_data.rs
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
use std::collections::HashMap;
use noirc_errors::Location;
use super::{ItemScope, LocalModuleId, ModuleDefId, ModuleId, PerNs};
use crate::ast::{Ident, ItemVisibility};
use crate::node_interner::{FuncId, GlobalId, StructId, TraitId, TypeAliasId};
use crate::token::SecondaryAttribute;
/// Contains the actual contents of a module: its parent (if one exists),
/// children, and scope with all definitions defined within the scope.
#[derive(Debug, PartialEq, Eq)]
pub struct ModuleData {
pub parent: Option<LocalModuleId>,
pub children: HashMap<Ident, LocalModuleId>,
/// Each child in the order they were declared in the parent module.
/// E.g. for a module containing `mod foo; mod bar; mod baz` this would
/// be `vec![foo, bar, baz]`.
pub child_declaration_order: Vec<LocalModuleId>,
/// Contains all definitions visible to the current module. This includes
/// all definitions in self.definitions as well as all imported definitions.
scope: ItemScope,
/// Contains only the definitions directly defined in the current module
definitions: ItemScope,
pub location: Location,
/// True if this module is a `contract Foo { ... }` module containing contract functions
pub is_contract: bool,
/// True if this module is actually a struct
pub is_struct: bool,
pub attributes: Vec<SecondaryAttribute>,
}
impl ModuleData {
pub fn new(
parent: Option<LocalModuleId>,
location: Location,
outer_attributes: Vec<SecondaryAttribute>,
inner_attributes: Vec<SecondaryAttribute>,
is_contract: bool,
is_struct: bool,
) -> ModuleData {
let mut attributes = outer_attributes;
attributes.extend(inner_attributes);
ModuleData {
parent,
children: HashMap::new(),
child_declaration_order: Vec::new(),
scope: ItemScope::default(),
definitions: ItemScope::default(),
location,
is_contract,
is_struct,
attributes,
}
}
pub fn scope(&self) -> &ItemScope {
&self.scope
}
pub fn definitions(&self) -> &ItemScope {
&self.definitions
}
fn declare(
&mut self,
name: Ident,
visibility: ItemVisibility,
item_id: ModuleDefId,
trait_id: Option<TraitId>,
) -> Result<(), (Ident, Ident)> {
self.scope.add_definition(name.clone(), visibility, item_id, trait_id)?;
if let ModuleDefId::ModuleId(child) = item_id {
self.child_declaration_order.push(child.local_id);
}
// definitions is a subset of self.scope so it is expected if self.scope.define_func_def
// returns without error, so will self.definitions.define_func_def.
self.definitions.add_definition(name, visibility, item_id, trait_id)
}
pub fn declare_function(
&mut self,
name: Ident,
visibility: ItemVisibility,
id: FuncId,
) -> Result<(), (Ident, Ident)> {
self.declare(name, visibility, id.into(), None)
}
pub fn declare_trait_function(
&mut self,
name: Ident,
id: FuncId,
trait_id: TraitId,
) -> Result<(), (Ident, Ident)> {
self.declare(name, ItemVisibility::Public, id.into(), Some(trait_id))
}
pub fn remove_function(&mut self, name: &Ident) {
self.scope.remove_definition(name);
self.definitions.remove_definition(name);
}
pub fn declare_global(
&mut self,
name: Ident,
visibility: ItemVisibility,
id: GlobalId,
) -> Result<(), (Ident, Ident)> {
self.declare(name, visibility, id.into(), None)
}
pub fn declare_struct(
&mut self,
name: Ident,
visibility: ItemVisibility,
id: StructId,
) -> Result<(), (Ident, Ident)> {
self.declare(name, visibility, ModuleDefId::TypeId(id), None)
}
pub fn declare_type_alias(
&mut self,
name: Ident,
visibility: ItemVisibility,
id: TypeAliasId,
) -> Result<(), (Ident, Ident)> {
self.declare(name, visibility, id.into(), None)
}
pub fn declare_trait(
&mut self,
name: Ident,
visibility: ItemVisibility,
id: TraitId,
) -> Result<(), (Ident, Ident)> {
self.declare(name, visibility, ModuleDefId::TraitId(id), None)
}
pub fn declare_child_module(
&mut self,
name: Ident,
visibility: ItemVisibility,
child_id: ModuleId,
) -> Result<(), (Ident, Ident)> {
self.declare(name, visibility, child_id.into(), None)
}
pub fn find_func_with_name(&self, name: &Ident) -> Option<FuncId> {
self.scope.find_func_with_name(name)
}
pub fn import(
&mut self,
name: Ident,
visibility: ItemVisibility,
id: ModuleDefId,
is_prelude: bool,
) -> Result<(), (Ident, Ident)> {
self.scope.add_item_to_namespace(name, visibility, id, None, is_prelude)
}
pub fn find_name(&self, name: &Ident) -> PerNs {
self.scope.find_name(name)
}
pub fn type_definitions(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
self.definitions.types().values().flat_map(|a| a.values().map(|(id, _, _)| *id))
}
/// Return an iterator over all definitions defined within this module,
/// excluding any type definitions.
pub fn value_definitions(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
self.definitions.values().values().flat_map(|a| a.values().map(|(id, _, _)| *id))
}
}