mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
separate imports from local symbols
This commit is contained in:
parent
5e47e4767e
commit
b8217bf9de
1 changed files with 79 additions and 13 deletions
|
@ -26,6 +26,8 @@ pub struct Scope {
|
||||||
|
|
||||||
/// The first `exposed_ident_count` identifiers are exposed
|
/// The first `exposed_ident_count` identifiers are exposed
|
||||||
exposed_ident_count: usize,
|
exposed_ident_count: usize,
|
||||||
|
|
||||||
|
imports: Vec<(Ident, Symbol, Region)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_aliases(var_store: &mut VarStore) -> VecMap<Symbol, Alias> {
|
fn add_aliases(var_store: &mut VarStore) -> VecMap<Symbol, Alias> {
|
||||||
|
@ -78,6 +80,7 @@ impl Scope {
|
||||||
aliases: VecMap::default(),
|
aliases: VecMap::default(),
|
||||||
// TODO(abilities): default abilities in scope
|
// TODO(abilities): default abilities in scope
|
||||||
abilities_store: AbilitiesStore::default(),
|
abilities_store: AbilitiesStore::default(),
|
||||||
|
imports: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +97,7 @@ impl Scope {
|
||||||
aliases: add_aliases(var_store),
|
aliases: add_aliases(var_store),
|
||||||
// TODO(abilities): default abilities in scope
|
// TODO(abilities): default abilities in scope
|
||||||
abilities_store: AbilitiesStore::default(),
|
abilities_store: AbilitiesStore::default(),
|
||||||
|
imports: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,15 +105,18 @@ impl Scope {
|
||||||
match self.idents.get_symbol(ident) {
|
match self.idents.get_symbol(ident) {
|
||||||
Some(symbol) => Ok(symbol),
|
Some(symbol) => Ok(symbol),
|
||||||
None => {
|
None => {
|
||||||
|
for (import, symbol, _) in self.imports.iter() {
|
||||||
|
if ident == import {
|
||||||
|
return Ok(*symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let error = RuntimeError::LookupNotInScope(
|
let error = RuntimeError::LookupNotInScope(
|
||||||
Loc {
|
Loc {
|
||||||
region,
|
region,
|
||||||
value: ident.clone(),
|
value: ident.clone(),
|
||||||
},
|
},
|
||||||
self.idents
|
self.idents_in_scope().map(|v| v.as_ref().into()).collect(),
|
||||||
.iter_idents()
|
|
||||||
.map(|v| v.as_ref().into())
|
|
||||||
.collect(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Err(error)
|
Err(error)
|
||||||
|
@ -117,9 +124,11 @@ impl Scope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
fn idents_in_scope(&self) -> impl Iterator<Item = Ident> + '_ {
|
fn idents_in_scope(&self) -> impl Iterator<Item = Ident> + '_ {
|
||||||
self.idents.iter_idents()
|
let it1 = self.idents.iter_idents();
|
||||||
|
let it2 = self.imports.iter().map(|t| t.0.clone());
|
||||||
|
|
||||||
|
it1.chain(it2)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_alias(&self, symbol: Symbol) -> Option<&Alias> {
|
pub fn lookup_alias(&self, symbol: Symbol) -> Option<&Alias> {
|
||||||
|
@ -235,7 +244,19 @@ impl Scope {
|
||||||
};
|
};
|
||||||
Err((original_region, shadow))
|
Err((original_region, shadow))
|
||||||
}
|
}
|
||||||
None => Ok(self.commit_introduction(ident, region)),
|
None => {
|
||||||
|
for (import, _, original_region) in self.imports.iter() {
|
||||||
|
if ident == import {
|
||||||
|
let shadow = Loc {
|
||||||
|
value: ident.clone(),
|
||||||
|
region,
|
||||||
|
};
|
||||||
|
return Err((*original_region, shadow));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(self.commit_introduction(ident, region))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,14 +338,15 @@ impl Scope {
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Result<(), (Symbol, Region)> {
|
) -> Result<(), (Symbol, Region)> {
|
||||||
match self.idents.get_symbol_and_region(&ident) {
|
for t in self.imports.iter() {
|
||||||
Some(shadowed) => Err(shadowed),
|
if t.0 == ident {
|
||||||
None => {
|
return Err((t.1, t.2));
|
||||||
self.idents.insert_unchecked(&ident, symbol, region);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.imports.push((ident, symbol, region));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_alias(
|
pub fn add_alias(
|
||||||
|
@ -641,4 +663,48 @@ mod test {
|
||||||
|
|
||||||
assert_eq!(&idents[builtin_count..], &[ident1, ident2, ident3,]);
|
assert_eq!(&idents[builtin_count..], &[ident1, ident2, ident3,]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn import_is_in_scope() {
|
||||||
|
let _register_module_debug_names = ModuleIds::default();
|
||||||
|
let mut scope = Scope::new(ModuleId::ATTR, IdentIds::default());
|
||||||
|
|
||||||
|
let ident = Ident::from("product");
|
||||||
|
let symbol = Symbol::LIST_PRODUCT;
|
||||||
|
let region = Region::zero();
|
||||||
|
|
||||||
|
assert!(scope.lookup(&ident, region).is_err());
|
||||||
|
|
||||||
|
assert!(scope.import(ident.clone(), symbol, region).is_ok());
|
||||||
|
|
||||||
|
assert!(scope.lookup(&ident, region).is_ok());
|
||||||
|
|
||||||
|
assert!(scope.idents_in_scope().any(|x| x == ident));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shadow_of_import() {
|
||||||
|
let _register_module_debug_names = ModuleIds::default();
|
||||||
|
let mut scope = Scope::new(ModuleId::ATTR, IdentIds::default());
|
||||||
|
|
||||||
|
let ident = Ident::from("product");
|
||||||
|
let symbol = Symbol::LIST_PRODUCT;
|
||||||
|
|
||||||
|
let region1 = Region::from_pos(Position { offset: 10 });
|
||||||
|
let region2 = Region::from_pos(Position { offset: 20 });
|
||||||
|
|
||||||
|
scope.import(ident.clone(), symbol, region1).unwrap();
|
||||||
|
|
||||||
|
let (original_region, _ident, shadow_symbol) =
|
||||||
|
scope.introduce(ident.clone(), region2).unwrap_err();
|
||||||
|
|
||||||
|
scope.register_debug_idents();
|
||||||
|
|
||||||
|
assert_ne!(symbol, shadow_symbol);
|
||||||
|
assert_eq!(original_region, region1);
|
||||||
|
|
||||||
|
let lookup = scope.lookup(&ident, Region::zero()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(symbol, lookup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue