mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 15:03:46 +00:00
Qualified lookups return params
This commit is contained in:
parent
96e2d32fa6
commit
9d26adb228
6 changed files with 112 additions and 42 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue