mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +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 crate::scope::{PendingAbilitiesInScope, Scope};
|
||||||
use roc_collections::{ImMap, MutSet, SendMap, VecMap, VecSet};
|
use roc_collections::{ImMap, MutSet, SendMap, VecMap, VecSet};
|
||||||
use roc_module::ident::{Ident, Lowercase, TagName};
|
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_parse::ast::{AssignedField, ExtractSpaces, Pattern, Tag, TypeAnnotation, TypeHeader};
|
||||||
use roc_problem::can::ShadowKind;
|
use roc_problem::can::ShadowKind;
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
|
@ -398,7 +398,7 @@ pub(crate) fn make_apply_symbol(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match env.qualified_lookup(scope, module_name, ident, region) {
|
match env.qualified_lookup(scope, module_name, ident, region) {
|
||||||
Ok(symbol) => {
|
Ok(LookedupSymbol { symbol, params: _ }) => {
|
||||||
references.insert_type_lookup(symbol, QualifiedReference::Qualified);
|
references.insert_type_lookup(symbol, QualifiedReference::Qualified);
|
||||||
Ok(symbol)
|
Ok(symbol)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ use roc_module::ident::Lowercase;
|
||||||
use roc_module::ident::ModuleName;
|
use roc_module::ident::ModuleName;
|
||||||
use roc_module::ident::QualifiedModuleName;
|
use roc_module::ident::QualifiedModuleName;
|
||||||
use roc_module::symbol::IdentId;
|
use roc_module::symbol::IdentId;
|
||||||
|
use roc_module::symbol::LookedupSymbol;
|
||||||
use roc_module::symbol::ModuleId;
|
use roc_module::symbol::ModuleId;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_parse::ast;
|
use roc_parse::ast;
|
||||||
|
@ -512,19 +513,21 @@ fn canonicalize_claimed_ability_impl<'a>(
|
||||||
let label_str = label.value;
|
let label_str = label.value;
|
||||||
let region = label.region;
|
let region = label.region;
|
||||||
|
|
||||||
let member_symbol =
|
let LookedupSymbol {
|
||||||
match env.qualified_lookup_with_module_id(scope, ability_home, label_str, region) {
|
symbol: member_symbol,
|
||||||
Ok(symbol) => symbol,
|
params: _,
|
||||||
Err(_) => {
|
} = match env.qualified_lookup_with_module_id(scope, ability_home, label_str, region) {
|
||||||
env.problem(Problem::NotAnAbilityMember {
|
Ok(symbol) => symbol,
|
||||||
ability,
|
Err(_) => {
|
||||||
name: label_str.to_owned(),
|
env.problem(Problem::NotAnAbilityMember {
|
||||||
region,
|
ability,
|
||||||
});
|
name: label_str.to_owned(),
|
||||||
|
region,
|
||||||
|
});
|
||||||
|
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// There are two options for how the implementation symbol is defined.
|
// 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 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,
|
scope,
|
||||||
ability_home,
|
ability_home,
|
||||||
label.value,
|
label.value,
|
||||||
|
|
|
@ -5,7 +5,10 @@ use crate::scope::Scope;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_collections::{MutMap, VecSet};
|
use roc_collections::{MutMap, VecSet};
|
||||||
use roc_module::ident::{Ident, ModuleName};
|
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_problem::can::{Problem, RuntimeError};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
|
|
||||||
|
@ -74,7 +77,7 @@ impl<'a> Env<'a> {
|
||||||
module_name_str: &str,
|
module_name_str: &str,
|
||||||
ident: &str,
|
ident: &str,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Result<Symbol, RuntimeError> {
|
) -> Result<LookedupSymbol, RuntimeError> {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
!module_name_str.is_empty(),
|
!module_name_str.is_empty(),
|
||||||
"Called env.qualified_lookup with an unqualified ident: {ident:?}"
|
"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);
|
let module_name = ModuleName::from(module_name_str);
|
||||||
|
|
||||||
match scope.modules.get_id(&module_name) {
|
match scope.modules.lookup(&module_name) {
|
||||||
Some(module_id) => self.qualified_lookup_help(scope, module_id, ident, region),
|
Some(lookedup_module) => {
|
||||||
|
self.qualified_lookup_help(scope, lookedup_module, ident, region)
|
||||||
|
}
|
||||||
None => Err(RuntimeError::ModuleNotImported {
|
None => Err(RuntimeError::ModuleNotImported {
|
||||||
module_name: module_name.clone(),
|
module_name: module_name.clone(),
|
||||||
imported_modules: scope
|
imported_modules: scope
|
||||||
|
@ -106,11 +111,11 @@ impl<'a> Env<'a> {
|
||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
ident: &str,
|
ident: &str,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Result<Symbol, RuntimeError> {
|
) -> Result<LookedupSymbol, RuntimeError> {
|
||||||
if !scope.modules.has_id(module_id) {
|
if let Some(module) = scope.modules.lookup_by_id(&module_id) {
|
||||||
Err(self.module_exists_but_not_imported(scope, module_id, region))
|
self.qualified_lookup_help(scope, module, ident, region)
|
||||||
} else {
|
} 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(
|
fn qualified_lookup_help(
|
||||||
&mut self,
|
&mut self,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
module_id: ModuleId,
|
module: LookedupModule,
|
||||||
ident: &str,
|
ident: &str,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Result<Symbol, RuntimeError> {
|
) -> Result<LookedupSymbol, RuntimeError> {
|
||||||
let is_type_name = ident.starts_with(|c: char| c.is_uppercase());
|
let is_type_name = ident.starts_with(|c: char| c.is_uppercase());
|
||||||
|
|
||||||
// You can do qualified lookups on your own module, e.g.
|
// 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 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) {
|
match scope.locals.ident_ids.get_id(ident) {
|
||||||
Some(ident_id) => {
|
Some(ident_id) => {
|
||||||
let symbol = Symbol::new(module_id, ident_id);
|
let symbol = Symbol::new(module.id, ident_id);
|
||||||
|
|
||||||
if is_type_name {
|
if is_type_name {
|
||||||
self.qualified_type_lookups.insert(symbol);
|
self.qualified_type_lookups.insert(symbol);
|
||||||
|
@ -137,7 +142,7 @@ impl<'a> Env<'a> {
|
||||||
self.qualified_value_lookups.insert(symbol);
|
self.qualified_value_lookups.insert(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(symbol)
|
Ok(LookedupSymbol::no_params(symbol))
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let error = RuntimeError::LookupNotInScope {
|
let error = RuntimeError::LookupNotInScope {
|
||||||
|
@ -157,10 +162,10 @@ impl<'a> Env<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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(exposed_ids) => match exposed_ids.get_id(ident) {
|
||||||
Some(ident_id) => {
|
Some(ident_id) => {
|
||||||
let symbol = Symbol::new(module_id, ident_id);
|
let symbol = Symbol::new(module.id, ident_id);
|
||||||
|
|
||||||
if is_type_name {
|
if is_type_name {
|
||||||
self.qualified_type_lookups.insert(symbol);
|
self.qualified_type_lookups.insert(symbol);
|
||||||
|
@ -168,12 +173,12 @@ impl<'a> Env<'a> {
|
||||||
self.qualified_value_lookups.insert(symbol);
|
self.qualified_value_lookups.insert(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(symbol)
|
Ok(module.into_symbol(symbol))
|
||||||
}
|
}
|
||||||
None => Err(RuntimeError::ValueNotExposed {
|
None => Err(RuntimeError::ValueNotExposed {
|
||||||
module_name: self
|
module_name: self
|
||||||
.qualified_module_ids
|
.qualified_module_ids
|
||||||
.get_name(module_id)
|
.get_name(module.id)
|
||||||
.expect("Module ID known, but not in the module IDs somehow")
|
.expect("Module ID known, but not in the module IDs somehow")
|
||||||
.as_inner()
|
.as_inner()
|
||||||
.clone(),
|
.clone(),
|
||||||
|
@ -182,7 +187,7 @@ impl<'a> Env<'a> {
|
||||||
exposed_values: exposed_ids.exposed_values(),
|
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.
|
// Since module_name was nonempty, this is a qualified var.
|
||||||
// Look it up in the env!
|
// Look it up in the env!
|
||||||
match env.qualified_lookup(scope, module_name, ident, region) {
|
match env.qualified_lookup(scope, module_name, ident, region) {
|
||||||
Ok(symbol) => {
|
Ok(lookedup_symbol) => {
|
||||||
output
|
output
|
||||||
.references
|
.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(
|
AbilityMember(
|
||||||
symbol,
|
lookedup_symbol.symbol,
|
||||||
Some(scope.abilities_store.fresh_specialization_id()),
|
Some(scope.abilities_store.fresh_specialization_id()),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Var(symbol, var_store.fresh())
|
Var(lookedup_symbol, var_store.fresh())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(problem) => {
|
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> {
|
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
|
||||||
match self.keys.iter().position(|x| x == key) {
|
match self.keys.iter().position(|x| x == key) {
|
||||||
None => None,
|
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> {
|
impl<K: PartialEq, V> Extend<(K, V)> for VecMap<K, V> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ScopeModules {
|
pub struct ScopeModules {
|
||||||
modules: VecMap<ModuleName, ModuleId>,
|
modules: VecMap<ModuleName, ModuleId>,
|
||||||
|
@ -629,6 +645,22 @@ pub struct ScopeModules {
|
||||||
params: Vec<Option<Symbol>>,
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum ScopeModuleSource {
|
pub enum ScopeModuleSource {
|
||||||
Builtin,
|
Builtin,
|
||||||
|
@ -637,12 +669,22 @@ pub enum ScopeModuleSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScopeModules {
|
impl ScopeModules {
|
||||||
pub fn get_id(&self, module_name: &ModuleName) -> Option<ModuleId> {
|
pub fn lookup(&self, module_name: &ModuleName) -> Option<LookedupModule> {
|
||||||
self.modules.get(module_name).copied()
|
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 {
|
pub fn lookup_by_id(&self, module_id: &ModuleId) -> Option<LookedupModule> {
|
||||||
self.sources.contains_key(&module_id)
|
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> {
|
pub fn available_names(&self) -> impl Iterator<Item = &ModuleName> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue