Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework parsed module storage and ordering algorithm. #6550

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Draft
131 changes: 131 additions & 0 deletions sway-core/src/concurrent_slab_mut.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
use std::{
fmt,
sync::{Arc, RwLock},
};

#[derive(Debug, Clone)]
pub struct Inner<T> {
pub items: Vec<Option<Arc<RwLock<T>>>>,
pub free_list: Vec<usize>,
}

impl<T> Default for Inner<T> {
fn default() -> Self {
Self {
items: Default::default(),
free_list: Default::default(),
}
}
}

#[derive(Debug)]
pub(crate) struct ConcurrentSlabMut<T> {
pub inner: RwLock<Inner<T>>,
}

impl<T> Clone for ConcurrentSlabMut<T>
where
T: Clone,
{
fn clone(&self) -> Self {
let inner = self.inner.read().unwrap();
Self {
inner: RwLock::new(inner.clone()),
}
}
}

impl<T> Default for ConcurrentSlabMut<T> {
fn default() -> Self {
Self {
inner: Default::default(),
}
}
}

pub struct ListDisplay<I> {
pub list: I,
}

impl<I: IntoIterator + Clone> fmt::Display for ListDisplay<I>
where
I::Item: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let fmt_elems = self
.list
.clone()
.into_iter()
.enumerate()
.map(|(i, value)| format!("{i:<10}\t->\t{value}"))
.collect::<Vec<_>>();
write!(f, "{}", fmt_elems.join("\n"))
}
}

impl<T> ConcurrentSlabMut<T>
where
T: Clone,
{
#[allow(dead_code)]
pub fn len(&self) -> usize {
let inner = self.inner.read().unwrap();
inner.items.len()
}

#[allow(dead_code)]
pub fn values(&self) -> Vec<Arc<RwLock<T>>> {
let inner = self.inner.read().unwrap();
inner.items.iter().filter_map(|x| x.clone()).collect()
}

pub fn insert(&self, value: T) -> usize {
self.insert_arc(Arc::new(RwLock::new(value)))
}

pub fn insert_arc(&self, value: Arc<RwLock<T>>) -> usize {
let mut inner = self.inner.write().unwrap();

if let Some(free) = inner.free_list.pop() {
assert!(inner.items[free].is_none());
inner.items[free] = Some(value);
free
} else {
inner.items.push(Some(value));
inner.items.len() - 1
}
}

pub fn get(&self, index: usize) -> Arc<RwLock<T>> {
let inner = self.inner.read().unwrap();
inner.items[index]
.as_ref()
.expect("invalid slab index for ConcurrentSlab::get")
.clone()
}

#[allow(dead_code)]
pub fn retain(&self, predicate: impl Fn(&usize, &mut Arc<RwLock<T>>) -> bool) {
let mut inner = self.inner.write().unwrap();

let Inner { items, free_list } = &mut *inner;
for (idx, item) in items.iter_mut().enumerate() {
if let Some(arc) = item {
if !predicate(&idx, arc) {
free_list.push(idx);
item.take();
}
}
}
}

#[allow(dead_code)]
pub fn clear(&self) {
let mut inner = self.inner.write().unwrap();
inner.items.clear();
inner.items.shrink_to(0);

inner.free_list.clear();
inner.free_list.shrink_to(0);
}
}
14 changes: 14 additions & 0 deletions sway-core/src/engine_threading.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
decl_engine::{parsed_engine::ParsedDeclEngine, DeclEngine},
language::parsed::ParsedModuleEngine,
query_engine::QueryEngine,
type_system::TypeEngine,
};
Expand All @@ -15,6 +16,7 @@ pub struct Engines {
type_engine: TypeEngine,
decl_engine: DeclEngine,
parsed_decl_engine: ParsedDeclEngine,
parsed_module_engine: ParsedModuleEngine,
query_engine: QueryEngine,
source_engine: SourceEngine,
}
Expand All @@ -32,6 +34,10 @@ impl Engines {
&self.parsed_decl_engine
}

pub fn pme(&self) -> &ParsedModuleEngine {
&self.parsed_module_engine
}

pub fn qe(&self) -> &QueryEngine {
&self.query_engine
}
Expand All @@ -46,6 +52,7 @@ impl Engines {
self.type_engine.clear_program(program_id);
self.decl_engine.clear_program(program_id);
self.parsed_decl_engine.clear_program(program_id);
// self.parsed_module_engine.clear_program(program_id);
}

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

/// Helps out some `thing: T` by adding `self` as context.
Expand Down Expand Up @@ -217,6 +225,12 @@ impl<T: DebugWithEngines> DebugWithEngines for Vec<T> {
}
}

impl DebugWithEngines for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
DisplayWithEngines::fmt(self, f, engines)
}
}

pub trait HashWithEngines {
fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines);
}
Expand Down
12 changes: 10 additions & 2 deletions sway-core/src/language/module.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
use sway_types::Ident;

use super::parsed::ParseModuleId;

/// The name used within a module to refer to one of its submodules.
///
/// If an alias was given to the `mod`, this will be the alias. If not, this is the submodule's
/// library name.
pub type ModName = Ident;

pub type ModPath = Vec<ModName>;

pub trait HasModuleId
{
/// Returns the associated module id.
fn module_id(&self) -> ParseModuleId;
}

pub trait HasModule<T>
where
T: HasSubmodules<Self>,
Self: Sized,
{
/// Returns the module of this submodule.
Expand All @@ -17,7 +26,6 @@ where

pub trait HasSubmodules<E>
where
E: HasModule<Self>,
Self: Sized,
{
/// Returns the submodules of this module.
Expand Down
2 changes: 0 additions & 2 deletions sway-core/src/language/parsed/declaration/function.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::{
engine_threading::*,
language::{parsed::*, *},
namespace::LexicalScopeId,
transform::{self, AttributeKind},
type_system::*,
};
Expand Down Expand Up @@ -29,7 +28,6 @@ pub struct FunctionDeclaration {
pub where_clause: Vec<(Ident, Vec<TraitConstraint>)>,
pub kind: FunctionDeclarationKind,
pub implementing_type: Option<Declaration>,
pub lexical_scope: LexicalScopeId,
}

impl EqWithEngines for FunctionDeclaration {}
Expand Down
2 changes: 2 additions & 0 deletions sway-core/src/language/parsed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod declaration;
mod expression;
mod include_statement;
mod module;
mod parsed_module_engine;
mod program;
mod use_statement;

Expand All @@ -12,6 +13,7 @@ pub use declaration::*;
pub use expression::*;
pub use include_statement::IncludeStatement;
pub use module::{ModuleEvaluationOrder, ParseModule, ParseSubmodule};
pub use parsed_module_engine::*;
pub use program::{ParseProgram, TreeType};
use sway_error::handler::ErrorEmitted;
use sway_types::span::Span;
Expand Down
62 changes: 55 additions & 7 deletions sway-core/src/language/parsed/module.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
use crate::{
language::{HasModule, HasSubmodules, ModName, Visibility},
transform,
language::{HasModule, HasModuleId, HasSubmodules, ModName, Visibility},
namespace::ModulePath,
transform, Engines,
};

use super::ParseTree;
use super::{ParseModuleId, ParseTree};
use sway_error::{
error::CompileError,
handler::{ErrorEmitted, Handler},
};
use sway_types::Span;

pub type ModuleHash = u64;
pub type ModuleEvaluationOrder = Vec<ModName>;
pub type ModuleEvaluationOrder = Vec<ParseModuleId>;

/// A module and its submodules in the form of a tree.
#[derive(Debug, Clone)]
pub struct ParseModule {
pub id: ParseModuleId,
/// Parent module id or `None` if its a root module.
pub parent: Option<ParseModuleId>,
/// The content of this module in the form of a `ParseTree`.
pub tree: ParseTree,
/// Submodules introduced within this module using the `dep` syntax in order of declaration.
Expand All @@ -25,20 +33,60 @@ pub struct ParseModule {
pub span: Span,
/// an hash used for caching the module
pub hash: ModuleHash,
pub name: Option<String>,
}

impl ParseModule {
/// Lookup the submodule at the given path.
pub fn lookup_submodule(
&self,
handler: &Handler,
engines: &Engines,
path: &ModulePath,
) -> Result<ParseModuleId, ErrorEmitted> {
let pme = engines.pme();
let mut module_id = self.id;
for ident in path.iter() {
let module_arc = pme.get(&module_id);
let module = module_arc.read().unwrap();
match module.submodules.iter().find(|(name, _)| name == ident) {
Some((_name, submod)) => module_id = submod.module,
None => {
return Err(handler.emit_err(CompileError::Internal(
"Cannot find submodule",
Span::dummy(),
)))
}
}
}
Ok(module_id)
}
}

impl HasModuleId for ParseModule {
fn module_id(&self) -> ParseModuleId {
self.id
}
}

/// A library module that was declared as a `mod` of another module.
///
/// Only submodules are guaranteed to be a `library`.
#[derive(Debug, Clone)]
pub struct ParseSubmodule {
pub module: ParseModule,
pub module: ParseModuleId,
pub mod_name_span: Span,
pub visibility: Visibility,
}

impl HasModule<ParseModule> for ParseSubmodule {
fn module(&self) -> &ParseModule {
impl HasModuleId for ParseSubmodule {
fn module_id(&self) -> ParseModuleId {
self.module
}
}

impl HasModule<ParseModuleId> for ParseSubmodule {
fn module(&self) -> &ParseModuleId {
&self.module
}
}
Expand Down
Loading