Skip to content

Commit 7671070

Browse files
committed
Rework parsed module storage and ordering algorithm.
1 parent 7b07216 commit 7671070

20 files changed

+482
-120
lines changed

sway-core/src/concurrent_slab_mut.rs

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
use std::{
2+
fmt,
3+
sync::{Arc, RwLock},
4+
};
5+
6+
#[derive(Debug, Clone)]
7+
pub struct Inner<T> {
8+
pub items: Vec<Option<Arc<RwLock<T>>>>,
9+
pub free_list: Vec<usize>,
10+
}
11+
12+
impl<T> Default for Inner<T> {
13+
fn default() -> Self {
14+
Self {
15+
items: Default::default(),
16+
free_list: Default::default(),
17+
}
18+
}
19+
}
20+
21+
#[derive(Debug)]
22+
pub(crate) struct ConcurrentSlabMut<T> {
23+
pub inner: RwLock<Inner<T>>,
24+
}
25+
26+
impl<T> Clone for ConcurrentSlabMut<T>
27+
where
28+
T: Clone,
29+
{
30+
fn clone(&self) -> Self {
31+
let inner = self.inner.read().unwrap();
32+
Self {
33+
inner: RwLock::new(inner.clone()),
34+
}
35+
}
36+
}
37+
38+
impl<T> Default for ConcurrentSlabMut<T> {
39+
fn default() -> Self {
40+
Self {
41+
inner: Default::default(),
42+
}
43+
}
44+
}
45+
46+
pub struct ListDisplay<I> {
47+
pub list: I,
48+
}
49+
50+
impl<I: IntoIterator + Clone> fmt::Display for ListDisplay<I>
51+
where
52+
I::Item: fmt::Display,
53+
{
54+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55+
let fmt_elems = self
56+
.list
57+
.clone()
58+
.into_iter()
59+
.enumerate()
60+
.map(|(i, value)| format!("{i:<10}\t->\t{value}"))
61+
.collect::<Vec<_>>();
62+
write!(f, "{}", fmt_elems.join("\n"))
63+
}
64+
}
65+
66+
impl<T> ConcurrentSlabMut<T>
67+
where
68+
T: Clone,
69+
{
70+
#[allow(dead_code)]
71+
pub fn len(&self) -> usize {
72+
let inner = self.inner.read().unwrap();
73+
inner.items.len()
74+
}
75+
76+
#[allow(dead_code)]
77+
pub fn values(&self) -> Vec<Arc<RwLock<T>>> {
78+
let inner = self.inner.read().unwrap();
79+
inner.items.iter().filter_map(|x| x.clone()).collect()
80+
}
81+
82+
pub fn insert(&self, value: T) -> usize {
83+
self.insert_arc(Arc::new(RwLock::new(value)))
84+
}
85+
86+
pub fn insert_arc(&self, value: Arc<RwLock<T>>) -> usize {
87+
let mut inner = self.inner.write().unwrap();
88+
89+
if let Some(free) = inner.free_list.pop() {
90+
assert!(inner.items[free].is_none());
91+
inner.items[free] = Some(value);
92+
free
93+
} else {
94+
inner.items.push(Some(value));
95+
inner.items.len() - 1
96+
}
97+
}
98+
99+
pub fn get(&self, index: usize) -> Arc<RwLock<T>> {
100+
let inner = self.inner.read().unwrap();
101+
inner.items[index]
102+
.as_ref()
103+
.expect("invalid slab index for ConcurrentSlab::get")
104+
.clone()
105+
}
106+
107+
#[allow(dead_code)]
108+
pub fn retain(&self, predicate: impl Fn(&usize, &mut Arc<RwLock<T>>) -> bool) {
109+
let mut inner = self.inner.write().unwrap();
110+
111+
let Inner { items, free_list } = &mut *inner;
112+
for (idx, item) in items.iter_mut().enumerate() {
113+
if let Some(arc) = item {
114+
if !predicate(&idx, arc) {
115+
free_list.push(idx);
116+
item.take();
117+
}
118+
}
119+
}
120+
}
121+
122+
#[allow(dead_code)]
123+
pub fn clear(&self) {
124+
let mut inner = self.inner.write().unwrap();
125+
inner.items.clear();
126+
inner.items.shrink_to(0);
127+
128+
inner.free_list.clear();
129+
inner.free_list.shrink_to(0);
130+
}
131+
}

sway-core/src/engine_threading.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::{
22
decl_engine::{parsed_engine::ParsedDeclEngine, DeclEngine},
3+
language::parsed::ParsedModuleEngine,
34
query_engine::QueryEngine,
45
type_system::TypeEngine,
56
};
@@ -15,6 +16,7 @@ pub struct Engines {
1516
type_engine: TypeEngine,
1617
decl_engine: DeclEngine,
1718
parsed_decl_engine: ParsedDeclEngine,
19+
parsed_module_engine: ParsedModuleEngine,
1820
query_engine: QueryEngine,
1921
source_engine: SourceEngine,
2022
}
@@ -32,6 +34,10 @@ impl Engines {
3234
&self.parsed_decl_engine
3335
}
3436

37+
pub fn pme(&self) -> &ParsedModuleEngine {
38+
&self.parsed_module_engine
39+
}
40+
3541
pub fn qe(&self) -> &QueryEngine {
3642
&self.query_engine
3743
}
@@ -46,6 +52,7 @@ impl Engines {
4652
self.type_engine.clear_program(program_id);
4753
self.decl_engine.clear_program(program_id);
4854
self.parsed_decl_engine.clear_program(program_id);
55+
// self.parsed_module_engine.clear_program(program_id);
4956
}
5057

5158
/// Removes all data associated with `source_id` from the declaration and type engines.
@@ -54,6 +61,7 @@ impl Engines {
5461
self.type_engine.clear_module(source_id);
5562
self.decl_engine.clear_module(source_id);
5663
self.parsed_decl_engine.clear_module(source_id);
64+
// self.parsed_module_engine.clear_module(source_id);
5765
}
5866

5967
/// Helps out some `thing: T` by adding `self` as context.

sway-core/src/language/module.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
use sway_types::Ident;
22

3+
use super::parsed::ParseModuleId;
4+
35
/// The name used within a module to refer to one of its submodules.
46
///
57
/// If an alias was given to the `mod`, this will be the alias. If not, this is the submodule's
68
/// library name.
79
pub type ModName = Ident;
810

11+
pub type ModPath = Vec<ModName>;
12+
13+
pub trait HasModuleId
14+
{
15+
/// Returns the associated module id.
16+
fn module_id(&self) -> ParseModuleId;
17+
}
18+
919
pub trait HasModule<T>
1020
where
11-
T: HasSubmodules<Self>,
1221
Self: Sized,
1322
{
1423
/// Returns the module of this submodule.
@@ -17,7 +26,6 @@ where
1726

1827
pub trait HasSubmodules<E>
1928
where
20-
E: HasModule<Self>,
2129
Self: Sized,
2230
{
2331
/// Returns the submodules of this module.

sway-core/src/language/parsed/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod declaration;
44
mod expression;
55
mod include_statement;
66
mod module;
7+
mod parsed_module_engine;
78
mod program;
89
mod use_statement;
910

@@ -12,6 +13,7 @@ pub use declaration::*;
1213
pub use expression::*;
1314
pub use include_statement::IncludeStatement;
1415
pub use module::{ModuleEvaluationOrder, ParseModule, ParseSubmodule};
16+
pub use parsed_module_engine::*;
1517
pub use program::{ParseProgram, TreeType};
1618
use sway_error::handler::ErrorEmitted;
1719
use sway_types::span::Span;

sway-core/src/language/parsed/module.rs

+23-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::{
2-
language::{HasModule, HasSubmodules, ModName, Visibility},
2+
language::{HasModule, HasModuleId, HasSubmodules, ModName, Visibility},
33
transform,
44
};
55

6-
use super::ParseTree;
6+
use super::{ParseModuleId, ParseTree};
77
use sway_types::Span;
88

99
pub type ModuleHash = u64;
@@ -12,6 +12,9 @@ pub type ModuleEvaluationOrder = Vec<ModName>;
1212
/// A module and its submodules in the form of a tree.
1313
#[derive(Debug, Clone)]
1414
pub struct ParseModule {
15+
pub id: ParseModuleId,
16+
/// Parent module id or `None` if its a root module.
17+
pub parent: Option<ParseModuleId>,
1518
/// The content of this module in the form of a `ParseTree`.
1619
pub tree: ParseTree,
1720
/// Submodules introduced within this module using the `dep` syntax in order of declaration.
@@ -25,20 +28,35 @@ pub struct ParseModule {
2528
pub span: Span,
2629
/// an hash used for caching the module
2730
pub hash: ModuleHash,
31+
pub name: Option<String>,
32+
}
33+
34+
impl HasModuleId for ParseModule
35+
{
36+
fn module_id(&self) -> ParseModuleId {
37+
return self.id
38+
}
2839
}
2940

3041
/// A library module that was declared as a `mod` of another module.
3142
///
3243
/// Only submodules are guaranteed to be a `library`.
3344
#[derive(Debug, Clone)]
3445
pub struct ParseSubmodule {
35-
pub module: ParseModule,
46+
pub module: ParseModuleId,
3647
pub mod_name_span: Span,
3748
pub visibility: Visibility,
3849
}
3950

40-
impl HasModule<ParseModule> for ParseSubmodule {
41-
fn module(&self) -> &ParseModule {
51+
impl HasModuleId for ParseSubmodule
52+
{
53+
fn module_id(&self) -> ParseModuleId {
54+
self.module
55+
}
56+
}
57+
58+
impl HasModule<ParseModuleId> for ParseSubmodule {
59+
fn module(&self) -> &ParseModuleId {
4260
&self.module
4361
}
4462
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use std::sync::{Arc, RwLock};
2+
3+
use crate::concurrent_slab_mut::ConcurrentSlabMut;
4+
5+
use super::ParseModule;
6+
7+
/// A identifier to uniquely refer to our parsed modules.
8+
#[derive(Default, PartialEq, Eq, Hash, Clone, Copy, Ord, PartialOrd, Debug)]
9+
pub struct ParseModuleId(usize);
10+
11+
impl ParseModuleId {
12+
pub fn new(index: usize) -> Self {
13+
ParseModuleId(index)
14+
}
15+
16+
/// Returns the index that identifies the type.
17+
pub fn index(&self) -> usize {
18+
self.0
19+
}
20+
21+
pub(crate) fn get(&self, engines: &crate::Engines) -> Arc<RwLock<ParseModule>> {
22+
engines.pme().get(self)
23+
}
24+
25+
pub fn read<R>(&self, engines: &crate::Engines, f: impl Fn(&ParseModule) -> R) -> R {
26+
let value = self.get(engines);
27+
let value = value.read().unwrap();
28+
f(&value)
29+
}
30+
31+
pub fn write<R>(
32+
&self,
33+
engines: &crate::Engines,
34+
mut f: impl FnMut(&mut ParseModule) -> R,
35+
) -> R {
36+
let value = self.get(engines);
37+
let mut value = value.write().unwrap();
38+
f(&mut value)
39+
}
40+
}
41+
42+
/// The Parsed Module Engine manages a relationship between module ids and their corresponding
43+
/// parsed module structures.
44+
#[derive(Debug, Default, Clone)]
45+
pub struct ParsedModuleEngine {
46+
slab: ConcurrentSlabMut<ParseModule>,
47+
}
48+
49+
impl ParsedModuleEngine {
50+
/// This function provides the namespace module corresponding to a specified module ID.
51+
pub fn get(&self, module_id: &ParseModuleId) -> Arc<RwLock<ParseModule>> {
52+
self.slab.get(module_id.index())
53+
}
54+
55+
pub fn read<R>(&self, module_id: &ParseModuleId, f: impl Fn(&ParseModule) -> R) -> R {
56+
let value = self.slab.get(module_id.index());
57+
let value = value.read().unwrap();
58+
f(&value)
59+
}
60+
61+
pub fn write<R>(&self, module_id: &ParseModuleId, f: impl Fn(&mut ParseModule) -> R) -> R {
62+
let value = self.slab.get(module_id.index());
63+
let mut value = value.write().unwrap();
64+
f(&mut value)
65+
}
66+
67+
pub fn insert(&self, value: ParseModule) -> ParseModuleId {
68+
let id = ParseModuleId(self.slab.insert(value));
69+
self.write(&id, |m| {
70+
m.id = id;
71+
});
72+
id
73+
}
74+
}

sway-core/src/language/parsed/program.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ use strum::EnumString;
22

33
use crate::Engines;
44

5-
use super::ParseModule;
5+
use super::ParseModuleId;
66

77
/// A parsed, but not yet type-checked, Sway program.
88
///
99
/// Includes all modules in the form of a `ParseModule` tree accessed via the `root`.
1010
#[derive(Debug, Clone)]
1111
pub struct ParseProgram {
1212
pub kind: TreeType,
13-
pub root: ParseModule,
13+
pub root: ParseModuleId,
1414
}
1515

1616
/// A Sway program can be either a contract, script, predicate, or a library.
@@ -46,6 +46,6 @@ impl std::fmt::Display for TreeType {
4646
impl ParseProgram {
4747
/// Excludes all test functions from the parse tree.
4848
pub(crate) fn exclude_tests(&mut self, engines: &Engines) {
49-
self.root.tree.exclude_tests(engines)
49+
self.root.write(engines, |m| m.tree.exclude_tests(engines))
5050
}
5151
}

0 commit comments

Comments
 (0)