Skip to content

Commit

Permalink
Handle namespace imports during symbol collection.
Browse files Browse the repository at this point in the history
  • Loading branch information
tritao committed Jun 13, 2024
1 parent 8878451 commit 48bd832
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 9 deletions.
1 change: 0 additions & 1 deletion sway-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,6 @@ pub fn parsed_to_ast(
package_name: &str,
retrigger_compilation: Option<Arc<AtomicBool>>,
) -> Result<ty::TyProgram, ErrorEmitted> {

let experimental = build_config
.map(|x| x.experimental)
.unwrap_or(ExperimentalFlags {
Expand Down
101 changes: 100 additions & 1 deletion sway-core/src/semantic_analysis/ast_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ impl ty::TyAstNode {
node: &AstNode,
) -> Result<(), ErrorEmitted> {
match node.content.clone() {
AstNodeContent::UseStatement(_stmt) => {}
AstNodeContent::UseStatement(stmt) => {
collect_use_statement(handler, engines, ctx, &stmt);
}
AstNodeContent::IncludeStatement(_i) => (),
AstNodeContent::Declaration(decl) => ty::TyDecl::collect(handler, engines, ctx, decl)?,
AstNodeContent::Expression(_expr) => (),
Expand Down Expand Up @@ -186,6 +188,103 @@ fn handle_item_trait_imports(
Ok(())
}

fn collect_use_statement(
handler: &Handler,
engines: &Engines,
ctx: &mut SymbolCollectionContext,
stmt: &UseStatement,
) {
let mut is_external = false;
if let Some(submodule) = ctx
.namespace
.module(engines)
.submodule(engines, &[stmt.call_path[0].clone()])
{
is_external |= submodule.read(engines, |m| m.is_external);
}
// We create an inner module for each module being processed during the collection.
// This does not play well with the existing way we use to lookup an external module.
// So check again starting from the root to make sure we find the right module.
// Clean this up once paths are normalized before collection and we can just rely on
// absolute paths.
if let Some(submodule) = ctx
.namespace
.root_module()
.submodule(engines, &[stmt.call_path[0].clone()])
{
is_external |= submodule.read(engines, |m| m.is_external);
}
let path = if is_external || stmt.is_absolute {
stmt.call_path.clone()
} else {
ctx.namespace.prepend_module_path(&stmt.call_path)
};
let _ = match stmt.import_type {
ImportType::Star => {
// try a standard starimport first
let star_import_handler = Handler::default();
let import = ctx.star_import(&star_import_handler, engines, &path);
if import.is_ok() {
handler.append(star_import_handler);
import
} else {
// if it doesn't work it could be an enum star import
if let Some((enum_name, path)) = path.split_last() {
let variant_import_handler = Handler::default();
let variant_import =
ctx.variant_star_import(&variant_import_handler, engines, path, enum_name);
if variant_import.is_ok() {
handler.append(variant_import_handler);
variant_import
} else {
handler.append(star_import_handler);
import
}
} else {
handler.append(star_import_handler);
import
}
}
}
ImportType::SelfImport(_) => ctx.self_import(handler, engines, &path, stmt.alias.clone()),
ImportType::Item(ref s) => {
// try a standard item import first
let item_import_handler = Handler::default();
let import =
ctx.item_import(&item_import_handler, engines, &path, s, stmt.alias.clone());

if import.is_ok() {
handler.append(item_import_handler);
import
} else {
// if it doesn't work it could be an enum variant import
if let Some((enum_name, path)) = path.split_last() {
let variant_import_handler = Handler::default();
let variant_import = ctx.variant_import(
&variant_import_handler,
engines,
path,
enum_name,
s,
stmt.alias.clone(),
);
if variant_import.is_ok() {
handler.append(variant_import_handler);
variant_import
} else {
handler.append(item_import_handler);
import
}
} else {
handler.append(item_import_handler);
import
}
}
}
};
}

// To be removed once TypeCheckContext is ported to use SymbolCollectionContext.
fn handle_use_statement(
ctx: &mut TypeCheckContext<'_>,
engines: &Engines,
Expand Down
90 changes: 90 additions & 0 deletions sway-core/src/semantic_analysis/collection_context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
language::{parsed::Declaration, Visibility},
namespace::ModulePath,
semantic_analysis::Namespace,
Engines,
};
Expand Down Expand Up @@ -90,4 +91,93 @@ impl SymbolCollectionContext {
)
})
}

/// Returns a mutable reference to the current namespace.
pub fn namespace_mut(&mut self) -> &mut Namespace {
&mut self.namespace
}

/// Returns a reference to the current namespace.
pub fn namespace(&self) -> &Namespace {
&self.namespace
}

/// Short-hand for performing a [Module::star_import] with `mod_path` as the destination.
pub(crate) fn star_import(
&mut self,
handler: &Handler,
engines: &Engines,
src: &ModulePath,
) -> Result<(), ErrorEmitted> {
let mod_path = self.namespace().mod_path.clone();
self.namespace_mut()
.root
.star_import(handler, engines, src, &mod_path)
}

/// Short-hand for performing a [Module::variant_star_import] with `mod_path` as the destination.
pub(crate) fn variant_star_import(
&mut self,
handler: &Handler,
engines: &Engines,
src: &ModulePath,
enum_name: &Ident,
) -> Result<(), ErrorEmitted> {
let mod_path = self.namespace().mod_path.clone();
self.namespace_mut()
.root
.variant_star_import(handler, engines, src, &mod_path, enum_name)
}

/// Short-hand for performing a [Module::self_import] with `mod_path` as the destination.
pub(crate) fn self_import(
&mut self,
handler: &Handler,
engines: &Engines,
src: &ModulePath,
alias: Option<Ident>,
) -> Result<(), ErrorEmitted> {
let mod_path = self.namespace().mod_path.clone();
self.namespace_mut()
.root
.self_import(handler, engines, src, &mod_path, alias)
}

/// Short-hand for performing a [Module::item_import] with `mod_path` as the destination.
pub(crate) fn item_import(
&mut self,
handler: &Handler,
engines: &Engines,
src: &ModulePath,
item: &Ident,
alias: Option<Ident>,
) -> Result<(), ErrorEmitted> {
let mod_path = self.namespace().mod_path.clone();
self.namespace_mut()
.root
.item_import(handler, engines, src, item, &mod_path, alias)
}

/// Short-hand for performing a [Module::variant_import] with `mod_path` as the destination.
#[allow(clippy::too_many_arguments)]
pub(crate) fn variant_import(
&mut self,
handler: &Handler,
engines: &Engines,
src: &ModulePath,
enum_name: &Ident,
variant_name: &Ident,
alias: Option<Ident>,
) -> Result<(), ErrorEmitted> {
let mod_path = self.namespace().mod_path.clone();
self.namespace_mut().root.variant_import(
handler,
engines,
src,
enum_name,
variant_name,
&mod_path,
alias,
)
}
}
12 changes: 6 additions & 6 deletions sway-core/src/semantic_analysis/namespace/lexical_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,11 +437,11 @@ impl Items {
item: &ResolvedDeclaration,
const_shadowing_mode: ConstShadowingMode| {
match (decl, item) {
(ResolvedDeclaration::Parsed(_decl), ResolvedDeclaration::Parsed(_item)) => {
// TODO: Do not handle any shadowing errors while handling parsed declarations yet,
// or else we will emit errors in a different order from the source code order.
// Update this once the full AST resolving pass is in.
}
// TODO: Do not handle any shadowing errors while handling parsed declarations yet,
// or else we will emit errors in a different order from the source code order.
// Update this once the full AST resolving pass is in.
(ResolvedDeclaration::Typed(_decl), ResolvedDeclaration::Parsed(_item)) => {}
(ResolvedDeclaration::Parsed(_decl), ResolvedDeclaration::Parsed(_item)) => {}
(ResolvedDeclaration::Typed(decl), ResolvedDeclaration::Typed(item)) => {
append_shadowing_error_typed(
ident,
Expand All @@ -452,7 +452,7 @@ impl Items {
const_shadowing_mode,
)
}
_ => unreachable!(),
_ => unreachable!()
}
};

Expand Down
5 changes: 4 additions & 1 deletion sway-core/src/semantic_analysis/namespace/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ impl Namespace {

Self {
init: init.clone(),
root: Root { module: init },
root: Root {
module: init,
resolve_options: root.resolve_options.clone(),
},
mod_path,
}
}
Expand Down

0 comments on commit 48bd832

Please sign in to comment.