Skip to content

Commit

Permalink
Handling use star in Semantics.
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomer-StarkWare committed Nov 13, 2024
1 parent a2b87c5 commit a0d581a
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 18 deletions.
52 changes: 51 additions & 1 deletion crates/cairo-lang-defs/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub trait DefsGroup:
#[salsa::interned]
fn intern_use(&self, id: UseLongId) -> UseId;
#[salsa::interned]
fn intern_global_use(&self, id: GlobalUseLongId) -> GlobalUseId;
#[salsa::interned]
fn intern_free_function(&self, id: FreeFunctionLongId) -> FreeFunctionId;
#[salsa::interned]
fn intern_impl_type_def(&self, id: ImplTypeDefLongId) -> ImplTypeDefId;
Expand Down Expand Up @@ -162,6 +164,10 @@ pub trait DefsGroup:
free_function_id: FreeFunctionId,
) -> Maybe<Option<ast::FunctionWithBody>>;
fn module_items(&self, module_id: ModuleId) -> Maybe<Arc<[ModuleItemId]>>;
fn module_global_uses(
&self,
module_id: ModuleId,
) -> Maybe<Arc<OrderedHashMap<GlobalUseId, ast::UsePathStar>>>;
/// Returns the stable ptr of the name of a module item.
fn module_item_name_stable_ptr(
&self,
Expand All @@ -174,6 +180,10 @@ pub trait DefsGroup:
) -> Maybe<Arc<OrderedHashMap<UseId, ast::UsePathLeaf>>>;
fn module_uses_ids(&self, module_id: ModuleId) -> Maybe<Arc<[UseId]>>;
fn module_use_by_id(&self, use_id: UseId) -> Maybe<Option<ast::UsePathLeaf>>;
fn module_global_use_by_id(
&self,
global_use_id: GlobalUseId,
) -> Maybe<Option<ast::UsePathStar>>;
fn module_structs(
&self,
module_id: ModuleId,
Expand Down Expand Up @@ -394,6 +404,7 @@ pub struct ModuleData {
impls: Arc<OrderedHashMap<ImplDefId, ast::ItemImpl>>,
extern_types: Arc<OrderedHashMap<ExternTypeId, ast::ItemExternType>>,
extern_functions: Arc<OrderedHashMap<ExternFunctionId, ast::ItemExternFunction>>,
global_uses: Arc<OrderedHashMap<GlobalUseId, ast::UsePathStar>>,

files: Vec<FileId>,
/// Generation info for each file. Virtual files have Some. Other files have None.
Expand Down Expand Up @@ -452,6 +463,7 @@ fn priv_module_data(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<ModuleData
let mut impls = OrderedHashMap::default();
let mut extern_types = OrderedHashMap::default();
let mut extern_functions = OrderedHashMap::default();
let mut global_uses = OrderedHashMap::default();
let mut aux_data = Vec::new();
let mut files = Vec::new();
let mut plugin_diagnostics = Vec::new();
Expand Down Expand Up @@ -487,6 +499,10 @@ fn priv_module_data(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<ModuleData
uses.insert(id, leaf);
items.push(ModuleItemId::Use(id));
}
for star in get_all_path_stars(db.upcast(), &us) {
let id = GlobalUseLongId(module_file_id, star.stable_ptr()).intern(db);
global_uses.insert(id, star);
}
}
ast::ModuleItem::FreeFunction(function) => {
let item_id =
Expand Down Expand Up @@ -568,6 +584,7 @@ fn priv_module_data(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<ModuleData
impls: impls.into(),
extern_types: extern_types.into(),
extern_functions: extern_functions.into(),
global_uses: global_uses.into(),
files,
generated_file_aux_data: aux_data,
plugin_diagnostics,
Expand Down Expand Up @@ -773,7 +790,24 @@ pub fn get_all_path_leaves(db: &dyn SyntaxGroup, use_item: &ast::ItemUse) -> Vec
ast::UsePath::Multi(use_path) => {
stack.extend(use_path.use_paths(db).elements(db).into_iter().rev())
}
ast::UsePath::Star(_) => todo!("Change function to collect `star` use as well."),
ast::UsePath::Star(_) => {}
}
}
res
}

/// Returns all the path stars under a given use item.
pub fn get_all_path_stars(db: &dyn SyntaxGroup, use_item: &ast::ItemUse) -> Vec<ast::UsePathStar> {
let mut res = vec![];
let mut stack = vec![use_item.use_path(db)];
while let Some(use_path) = stack.pop() {
match use_path {
ast::UsePath::Leaf(_) => {}
ast::UsePath::Single(use_path) => stack.push(use_path.use_path(db)),
ast::UsePath::Multi(use_path) => {
stack.extend(use_path.use_paths(db).elements(db).into_iter().rev())
}
ast::UsePath::Star(use_path) => res.push(use_path),
}
}
res
Expand Down Expand Up @@ -853,6 +887,15 @@ pub fn module_use_by_id(db: &dyn DefsGroup, use_id: UseId) -> Maybe<Option<ast::
Ok(module_uses.get(&use_id).cloned())
}

/// Returns the `use *` of the given module, by its ID.
pub fn module_global_use_by_id(
db: &dyn DefsGroup,
global_use_id: GlobalUseId,
) -> Maybe<Option<ast::UsePathStar>> {
let module_global_uses = db.module_global_uses(global_use_id.module_file_id(db.upcast()).0)?;
Ok(module_global_uses.get(&global_use_id).cloned())
}

/// Returns all the structs of the given module.
pub fn module_structs(
db: &dyn DefsGroup,
Expand Down Expand Up @@ -1038,6 +1081,13 @@ fn module_items(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[ModuleIte
Ok(db.priv_module_data(module_id)?.items)
}

fn module_global_uses(
db: &dyn DefsGroup,
module_id: ModuleId,
) -> Maybe<Arc<OrderedHashMap<GlobalUseId, ast::UsePathStar>>> {
Ok(db.priv_module_data(module_id)?.global_uses)
}

fn module_item_name_stable_ptr(
db: &dyn DefsGroup,
module_id: ModuleId,
Expand Down
7 changes: 7 additions & 0 deletions crates/cairo-lang-defs/src/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,13 @@ define_top_level_language_element_id!(
lookup_intern_constant,
intern_constant
);
define_language_element_id_basic!(
GlobalUseId,
GlobalUseLongId,
ast::UsePathStar,
lookup_intern_global_use,
intern_global_use
);
define_top_level_language_element_id!(
UseId,
UseLongId,
Expand Down
15 changes: 11 additions & 4 deletions crates/cairo-lang-semantic/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::diagnostic_utils::StableLocation;
use cairo_lang_defs::ids::{
ConstantId, EnumId, ExternFunctionId, ExternTypeId, FreeFunctionId, FunctionTitleId,
FunctionWithBodyId, GenericParamId, GenericTypeId, ImplAliasId, ImplConstantDefId, ImplDefId,
ImplFunctionId, ImplImplDefId, ImplItemId, ImplTypeDefId, LanguageElementId, LookupItemId,
ModuleId, ModuleItemId, ModuleTypeAliasId, StructId, TraitConstantId, TraitFunctionId, TraitId,
TraitImplId, TraitItemId, TraitTypeId, UseId, VariantId,
FunctionWithBodyId, GenericParamId, GenericTypeId, GlobalUseId, ImplAliasId, ImplConstantDefId,
ImplDefId, ImplFunctionId, ImplImplDefId, ImplItemId, ImplTypeDefId, LanguageElementId,
LookupItemId, ModuleId, ModuleItemId, ModuleTypeAliasId, StructId, TraitConstantId,
TraitFunctionId, TraitId, TraitImplId, TraitItemId, TraitTypeId, UseId, VariantId,
};
use cairo_lang_diagnostics::{Diagnostics, DiagnosticsBuilder, Maybe};
use cairo_lang_filesystem::db::{AsFilesGroupMut, FilesGroup};
Expand Down Expand Up @@ -175,6 +175,13 @@ pub trait SemanticGroup:
#[salsa::cycle(items::us::use_resolver_data_cycle)]
fn use_resolver_data(&self, use_id: UseId) -> Maybe<Arc<ResolverData>>;

// Global Use.
// ====
/// Private query to compute data about a global use.
#[salsa::invoke(items::us::priv_global_use_semantic_data)]
fn priv_global_use_semantic_data(&self, use_id: GlobalUseId)
-> Maybe<items::us::UseGlobalData>;

// Module.
// ====

Expand Down
25 changes: 24 additions & 1 deletion crates/cairo-lang-semantic/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::corelib::LiteralError;
use crate::db::SemanticGroup;
use crate::expr::inference::InferenceError;
use crate::items::feature_kind::FeatureMarkerDiagnostic;
use crate::resolve::ResolvedConcreteItem;
use crate::resolve::{ResolvedConcreteItem, ResolvedGenericItem};
use crate::types::peel_snapshots;
use crate::{ConcreteTraitId, semantic};

Expand Down Expand Up @@ -633,6 +633,9 @@ impl DiagnosticEntry for SemanticDiagnostic {
SemanticDiagnosticKind::NameDefinedMultipleTimes(name) => {
format!("The name `{name}` is defined multiple times.")
}
SemanticDiagnosticKind::NonPrivateUseStar => {
"`pub` not supported for global `use`.".into()
}
SemanticDiagnosticKind::NamedArgumentsAreNotSupported => {
"Named arguments are not supported in this context.".into()
}
Expand Down Expand Up @@ -1162,6 +1165,7 @@ pub enum SemanticDiagnosticKind {
PanicableExternFunction,
PluginDiagnostic(PluginDiagnostic),
NameDefinedMultipleTimes(SmolStr),
NonPrivateUseStar,
NamedArgumentsAreNotSupported,
ArgPassedToNegativeImpl,
UnnamedArgumentFollowsNamed,
Expand Down Expand Up @@ -1302,6 +1306,25 @@ impl From<&ResolvedConcreteItem> for ElementKind {
}
}
}
impl From<&ResolvedGenericItem> for ElementKind {
fn from(val: &ResolvedGenericItem) -> Self {
match val {
ResolvedGenericItem::GenericConstant(_) => ElementKind::Constant,
ResolvedGenericItem::Module(_) => ElementKind::Module,
ResolvedGenericItem::GenericFunction(_) => ElementKind::Function,
ResolvedGenericItem::TraitFunction(_) => ElementKind::TraitFunction,
ResolvedGenericItem::GenericType(_) | ResolvedGenericItem::GenericTypeAlias(_) => {
ElementKind::Type
}
ResolvedGenericItem::Variant(_) => ElementKind::Variant,
ResolvedGenericItem::Trait(_) => ElementKind::Trait,
ResolvedGenericItem::Impl(_) | ResolvedGenericItem::GenericImplAlias(_) => {
ElementKind::Impl
}
ResolvedGenericItem::Variable(_) => ElementKind::Variable,
}
}
}
impl Display for ElementKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let res = match self {
Expand Down
7 changes: 4 additions & 3 deletions crates/cairo-lang-semantic/src/expr/inference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use std::ops::{Deref, DerefMut};
use cairo_lang_debug::DebugWithDb;
use cairo_lang_defs::ids::{
ConstantId, EnumId, ExternFunctionId, ExternTypeId, FreeFunctionId, GenericParamId,
ImplAliasId, ImplDefId, ImplFunctionId, ImplImplDefId, LanguageElementId, LocalVarId,
LookupItemId, MemberId, ParamId, StructId, TraitConstantId, TraitFunctionId, TraitId,
TraitImplId, TraitTypeId, VarId, VariantId,
GlobalUseId, ImplAliasId, ImplDefId, ImplFunctionId, ImplImplDefId, LanguageElementId,
LocalVarId, LookupItemId, MemberId, ParamId, StructId, TraitConstantId, TraitFunctionId,
TraitId, TraitImplId, TraitTypeId, VarId, VariantId,
};
use cairo_lang_diagnostics::{DiagnosticAdded, Maybe, skip_diagnostic};
use cairo_lang_proc_macros::{DebugWithDb, SemanticObject};
Expand Down Expand Up @@ -86,6 +86,7 @@ pub enum InferenceId {
ImplAliasImplDef(ImplAliasId),
GenericParam(GenericParamId),
GenericImplParamTrait(GenericParamId),
GlobalUseStar(GlobalUseId),
Canonical,
/// For resolving that will not be used anywhere in the semantic model.
NoContext,
Expand Down
51 changes: 51 additions & 0 deletions crates/cairo-lang-semantic/src/expr/semantic_test_data/use
Original file line number Diff line number Diff line change
Expand Up @@ -1022,3 +1022,54 @@ Block(
)

//! > expected_diagnostics

//! > ==========================================================================

//! > Testing use star without implementation in Semantic

//! > test_runner_name
test_expr_semantics(expect_diagnostics: true)

//! > module_code
/// TODO(Tomer-StarkWare): Implement use star in Semantic
pub mod a {
const C: u8 = 2;
}
pub mod b {
use super::a::*;
}

//! > function_body

//! > expr_code
{
let _s = b::C;
}

//! > expected_semantics
Block(
ExprBlock {
statements: [
Let(
StatementLet {
pattern: Variable(
_s,
),
expr: Missing(
ExprMissing {
ty: <missing>,
},
),
},
),
],
tail: None,
ty: (),
},
)

//! > expected_diagnostics
error: Identifier not found.
--> lib.cairo:10:17
let _s = b::C;
^
20 changes: 18 additions & 2 deletions crates/cairo-lang-semantic/src/items/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::sync::Arc;

use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::ids::{
LanguageElementId, LookupItemId, ModuleId, ModuleItemId, NamedLanguageElementId, TraitId,
GlobalUseId, LanguageElementId, LookupItemId, ModuleId, ModuleItemId, NamedLanguageElementId,
TraitId,
};
use cairo_lang_diagnostics::{Diagnostics, DiagnosticsBuilder, Maybe};
use cairo_lang_syntax::attribute::structured::{Attribute, AttributeListStructurize};
Expand Down Expand Up @@ -32,6 +33,7 @@ pub struct ModuleItemInfo {
pub struct ModuleSemanticData {
/// The items in the module without duplicates.
pub items: OrderedHashMap<SmolStr, ModuleItemInfo>,
pub global_uses: OrderedHashMap<GlobalUseId, Visibility>,
pub diagnostics: Diagnostics<SemanticDiagnostic>,
}

Expand Down Expand Up @@ -110,7 +112,21 @@ pub fn priv_module_semantic_data(
);
}
}
Ok(Arc::new(ModuleSemanticData { items, diagnostics: diagnostics.build() }))

let global_uses = db
.module_global_uses(module_id)?
.iter()
.map(|(global_use_id, use_path_star)| {
let item = ast::UsePath::Star(use_path_star.clone()).get_item(syntax_db);
let visibility = item.visibility(syntax_db);
// TODO(Tomer-StarkWare): Add implementation for public imports.
if !matches!(visibility, ast::Visibility::Default(_)) {
diagnostics.report(use_path_star, SemanticDiagnosticKind::NonPrivateUseStar);
}
(*global_use_id, Visibility::Private)
})
.collect();
Ok(Arc::new(ModuleSemanticData { items, global_uses, diagnostics: diagnostics.build() }))
}

pub fn module_item_by_name(
Expand Down
Loading

0 comments on commit a0d581a

Please sign in to comment.