Qualified lookups return params

This commit is contained in:
Agus Zubiaga 2024-05-09 21:56:41 -03:00
parent 96e2d32fa6
commit 9d26adb228
No known key found for this signature in database
6 changed files with 112 additions and 42 deletions

View file

@ -3,7 +3,7 @@ use crate::procedure::{QualifiedReference, References};
use crate::scope::{PendingAbilitiesInScope, Scope};
use roc_collections::{ImMap, MutSet, SendMap, VecMap, VecSet};
use roc_module::ident::{Ident, Lowercase, TagName};
use roc_module::symbol::Symbol;
use roc_module::symbol::{LookedupSymbol, Symbol};
use roc_parse::ast::{AssignedField, ExtractSpaces, Pattern, Tag, TypeAnnotation, TypeHeader};
use roc_problem::can::ShadowKind;
use roc_region::all::{Loc, Region};
@ -398,7 +398,7 @@ pub(crate) fn make_apply_symbol(
}
} else {
match env.qualified_lookup(scope, module_name, ident, region) {
Ok(symbol) => {
Ok(LookedupSymbol { symbol, params: _ }) => {
references.insert_type_lookup(symbol, QualifiedReference::Qualified);
Ok(symbol)
}

View file

@ -32,6 +32,7 @@ use roc_module::ident::Lowercase;
use roc_module::ident::ModuleName;
use roc_module::ident::QualifiedModuleName;
use roc_module::symbol::IdentId;
use roc_module::symbol::LookedupSymbol;
use roc_module::symbol::ModuleId;
use roc_module::symbol::Symbol;
use roc_parse::ast;
@ -512,19 +513,21 @@ fn canonicalize_claimed_ability_impl<'a>(
let label_str = label.value;
let region = label.region;
let member_symbol =
match env.qualified_lookup_with_module_id(scope, ability_home, label_str, region) {
Ok(symbol) => symbol,
Err(_) => {
env.problem(Problem::NotAnAbilityMember {
ability,
name: label_str.to_owned(),
region,
});
let LookedupSymbol {
symbol: member_symbol,
params: _,
} = match env.qualified_lookup_with_module_id(scope, ability_home, label_str, region) {
Ok(symbol) => symbol,
Err(_) => {
env.problem(Problem::NotAnAbilityMember {
ability,
name: label_str.to_owned(),
region,
});
return Err(());
}
};
return Err(());
}
};
// There are two options for how the implementation symbol is defined.
//
@ -604,7 +607,10 @@ fn canonicalize_claimed_ability_impl<'a>(
};
let impl_region = value.region;
let member_symbol = match env.qualified_lookup_with_module_id(
let LookedupSymbol {
symbol: member_symbol,
params: _,
} = match env.qualified_lookup_with_module_id(
scope,
ability_home,
label.value,

View file

@ -5,7 +5,10 @@ use crate::scope::Scope;
use bumpalo::Bump;
use roc_collections::{MutMap, VecSet};
use roc_module::ident::{Ident, ModuleName};
use roc_module::symbol::{IdentIdsByModule, ModuleId, PQModuleName, PackageModuleIds, Symbol};
use roc_module::symbol::{
IdentIdsByModule, LookedupModule, LookedupSymbol, ModuleId, PQModuleName, PackageModuleIds,
Symbol,
};
use roc_problem::can::{Problem, RuntimeError};
use roc_region::all::{Loc, Region};
@ -74,7 +77,7 @@ impl<'a> Env<'a> {
module_name_str: &str,
ident: &str,
region: Region,
) -> Result<Symbol, RuntimeError> {
) -> Result<LookedupSymbol, RuntimeError> {
debug_assert!(
!module_name_str.is_empty(),
"Called env.qualified_lookup with an unqualified ident: {ident:?}"
@ -82,8 +85,10 @@ impl<'a> Env<'a> {
let module_name = ModuleName::from(module_name_str);
match scope.modules.get_id(&module_name) {
Some(module_id) => self.qualified_lookup_help(scope, module_id, ident, region),
match scope.modules.lookup(&module_name) {
Some(lookedup_module) => {
self.qualified_lookup_help(scope, lookedup_module, ident, region)
}
None => Err(RuntimeError::ModuleNotImported {
module_name: module_name.clone(),
imported_modules: scope
@ -106,11 +111,11 @@ impl<'a> Env<'a> {
module_id: ModuleId,
ident: &str,
region: Region,
) -> Result<Symbol, RuntimeError> {
if !scope.modules.has_id(module_id) {
Err(self.module_exists_but_not_imported(scope, module_id, region))
) -> Result<LookedupSymbol, RuntimeError> {
if let Some(module) = scope.modules.lookup_by_id(&module_id) {
self.qualified_lookup_help(scope, module, ident, region)
} else {
self.qualified_lookup_help(scope, module_id, ident, region)
Err(self.module_exists_but_not_imported(scope, module_id, region))
}
}
@ -118,18 +123,18 @@ impl<'a> Env<'a> {
fn qualified_lookup_help(
&mut self,
scope: &Scope,
module_id: ModuleId,
module: LookedupModule,
ident: &str,
region: Region,
) -> Result<Symbol, RuntimeError> {
) -> Result<LookedupSymbol, RuntimeError> {
let is_type_name = ident.starts_with(|c: char| c.is_uppercase());
// You can do qualified lookups on your own module, e.g.
// if I'm in the Foo module, I can do a `Foo.bar` lookup.
if module_id == self.home {
if module.id == self.home {
match scope.locals.ident_ids.get_id(ident) {
Some(ident_id) => {
let symbol = Symbol::new(module_id, ident_id);
let symbol = Symbol::new(module.id, ident_id);
if is_type_name {
self.qualified_type_lookups.insert(symbol);
@ -137,7 +142,7 @@ impl<'a> Env<'a> {
self.qualified_value_lookups.insert(symbol);
}
Ok(symbol)
Ok(LookedupSymbol::no_params(symbol))
}
None => {
let error = RuntimeError::LookupNotInScope {
@ -157,10 +162,10 @@ impl<'a> Env<'a> {
}
}
} else {
match self.dep_idents.get(&module_id) {
match self.dep_idents.get(&module.id) {
Some(exposed_ids) => match exposed_ids.get_id(ident) {
Some(ident_id) => {
let symbol = Symbol::new(module_id, ident_id);
let symbol = Symbol::new(module.id, ident_id);
if is_type_name {
self.qualified_type_lookups.insert(symbol);
@ -168,12 +173,12 @@ impl<'a> Env<'a> {
self.qualified_value_lookups.insert(symbol);
}
Ok(symbol)
Ok(module.into_symbol(symbol))
}
None => Err(RuntimeError::ValueNotExposed {
module_name: self
.qualified_module_ids
.get_name(module_id)
.get_name(module.id)
.expect("Module ID known, but not in the module IDs somehow")
.as_inner()
.clone(),
@ -182,7 +187,7 @@ impl<'a> Env<'a> {
exposed_values: exposed_ids.exposed_values(),
}),
},
_ => Err(self.module_exists_but_not_imported(scope, module_id, region)),
_ => Err(self.module_exists_but_not_imported(scope, module.id, region)),
}
}
}

View file

@ -1884,19 +1884,23 @@ fn canonicalize_var_lookup(
// Since module_name was nonempty, this is a qualified var.
// Look it up in the env!
match env.qualified_lookup(scope, module_name, ident, region) {
Ok(symbol) => {
Ok(lookedup_symbol) => {
output
.references
.insert_value_lookup(symbol, QualifiedReference::Qualified);
.insert_value_lookup(lookedup_symbol.symbol, QualifiedReference::Qualified);
if scope.abilities_store.is_ability_member_name(symbol) {
if scope
.abilities_store
.is_ability_member_name(lookedup_symbol.symbol)
{
// todo(agus): params for abilities?
AbilityMember(
symbol,
lookedup_symbol.symbol,
Some(scope.abilities_store.fresh_specialization_id()),
var_store.fresh(),
)
} else {
Var(symbol, var_store.fresh())
Var(lookedup_symbol, var_store.fresh())
}
}
Err(problem) => {

View file

@ -84,6 +84,13 @@ impl<K: PartialEq, V> VecMap<K, V> {
}
}
pub fn get_with_index(&self, key: &K) -> Option<(usize, &V)> {
self.keys
.iter()
.position(|x| x == key)
.map(|index| (index, &self.values[index]))
}
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
match self.keys.iter().position(|x| x == key) {
None => None,
@ -152,6 +159,12 @@ impl<K: PartialEq, V> VecMap<K, V> {
}
}
impl<K, V: PartialEq> VecMap<K, V> {
pub fn get_index_by_value(&self, value: &V) -> Option<usize> {
self.values.iter().position(|x| x == value)
}
}
impl<K: PartialEq, V> Extend<(K, V)> for VecMap<K, V> {
#[inline(always)]
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {

View file

@ -622,6 +622,22 @@ impl ModuleIds {
}
}
#[derive(Debug, Clone)]
pub struct LookedupSymbol {
pub symbol: Symbol,
pub params: Option<Symbol>,
}
impl LookedupSymbol {
pub fn new(symbol: Symbol, params: Option<Symbol>) -> Self {
Self { symbol, params }
}
pub fn no_params(symbol: Symbol) -> Self {
Self::new(symbol, None)
}
}
#[derive(Debug, Clone)]
pub struct ScopeModules {
modules: VecMap<ModuleName, ModuleId>,
@ -629,6 +645,22 @@ pub struct ScopeModules {
params: Vec<Option<Symbol>>,
}
pub struct LookedupModule {
pub id: ModuleId,
pub params: Option<Symbol>,
}
impl LookedupModule {
pub fn into_symbol(&self, symbol: Symbol) -> LookedupSymbol {
debug_assert_eq!(symbol.module_id(), self.id);
LookedupSymbol {
symbol,
params: self.params,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScopeModuleSource {
Builtin,
@ -637,12 +669,22 @@ pub enum ScopeModuleSource {
}
impl ScopeModules {
pub fn get_id(&self, module_name: &ModuleName) -> Option<ModuleId> {
self.modules.get(module_name).copied()
pub fn lookup(&self, module_name: &ModuleName) -> Option<LookedupModule> {
self.modules
.get_with_index(module_name)
.map(|(index, module_id)| LookedupModule {
id: *module_id,
params: self.params.get(index).copied().unwrap(),
})
}
pub fn has_id(&self, module_id: ModuleId) -> bool {
self.sources.contains_key(&module_id)
pub fn lookup_by_id(&self, module_id: &ModuleId) -> Option<LookedupModule> {
self.modules
.get_index_by_value(module_id)
.map(|index| LookedupModule {
id: *module_id,
params: self.params.get(index).copied().unwrap(),
})
}
pub fn available_names(&self) -> impl Iterator<Item = &ModuleName> {