mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-09-11 03:45:29 +03:00
Improve errors on conflits of imported names
This commit is contained in:
parent
234ebdbe98
commit
3ac966cf8c
@ -42,6 +42,7 @@ impl ParseBook {
|
|||||||
pub fn contains_def(&self, name: &Name) -> bool {
|
pub fn contains_def(&self, name: &Name) -> bool {
|
||||||
self.fun_defs.contains_key(name) || self.imp_defs.contains_key(name)
|
self.fun_defs.contains_key(name) || self.imp_defs.contains_key(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_builtin_def(&self, name: &Name) -> Option<bool> {
|
pub fn contains_builtin_def(&self, name: &Name) -> Option<bool> {
|
||||||
self.fun_defs.get(name).map(|d| d.is_builtin()).or(self.imp_defs.get(name).map(|(_, s)| s.is_builtin()))
|
self.fun_defs.get(name).map(|d| d.is_builtin()).or(self.imp_defs.get(name).map(|(_, s)| s.is_builtin()))
|
||||||
}
|
}
|
||||||
@ -941,6 +942,9 @@ impl<'a> TermParser<'a> {
|
|||||||
return self.with_ctx(Err(msg), span);
|
return self.with_ctx(Err(msg), span);
|
||||||
} else {
|
} else {
|
||||||
for ctr in adt.ctrs.keys() {
|
for ctr in adt.ctrs.keys() {
|
||||||
|
if let Some(builtin) = book.contains_builtin_def(ctr) {
|
||||||
|
return Err(TermParser::redefinition_of_function_msg(builtin, ctr));
|
||||||
|
}
|
||||||
match book.ctrs.entry(ctr.clone()) {
|
match book.ctrs.entry(ctr.clone()) {
|
||||||
indexmap::map::Entry::Vacant(e) => _ = e.insert(nam.clone()),
|
indexmap::map::Entry::Vacant(e) => _ = e.insert(nam.clone()),
|
||||||
indexmap::map::Entry::Occupied(e) => {
|
indexmap::map::Entry::Occupied(e) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
diagnostics::{Diagnostics, WarningType},
|
diagnostics::{Diagnostics, WarningType},
|
||||||
fun::{load_book::do_parse_book, parser::ParseBook, Adt, Name, Source, Term},
|
fun::{load_book::do_parse_book, parser::ParseBook, Adt, Definition, Name, Source, Term},
|
||||||
imp::{Expr, Stmt},
|
imp::{Expr, Stmt},
|
||||||
};
|
};
|
||||||
use indexmap::{map::Entry, IndexMap};
|
use indexmap::{map::Entry, IndexMap};
|
||||||
@ -129,7 +129,7 @@ impl ParseBook {
|
|||||||
imp_defs.chain(fun_defs).chain(adts).chain(ctrs)
|
imp_defs.chain(fun_defs).chain(adts).chain(ctrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_imports(&mut self, diag: &mut Diagnostics) -> Result<(), String> {
|
pub fn apply_imports(&mut self, diag: &mut Diagnostics) -> Result<(), Diagnostics> {
|
||||||
self.apply_imports_go(None, diag)
|
self.apply_imports_go(None, diag)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ impl ParseBook {
|
|||||||
&mut self,
|
&mut self,
|
||||||
main_imports: Option<&ImportsMap>,
|
main_imports: Option<&ImportsMap>,
|
||||||
diag: &mut Diagnostics,
|
diag: &mut Diagnostics,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), Diagnostics> {
|
||||||
self.load_packages(main_imports, diag)?;
|
self.load_packages(main_imports, diag)?;
|
||||||
self.apply_import_binds(main_imports, diag);
|
self.apply_import_binds(main_imports, diag);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -149,7 +149,9 @@ impl ParseBook {
|
|||||||
&mut self,
|
&mut self,
|
||||||
main_imports: Option<&ImportsMap>,
|
main_imports: Option<&ImportsMap>,
|
||||||
diag: &mut Diagnostics,
|
diag: &mut Diagnostics,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), Diagnostics> {
|
||||||
|
diag.start_pass();
|
||||||
|
|
||||||
for (src, mut package) in std::mem::take(&mut self.imports.pkgs) {
|
for (src, mut package) in std::mem::take(&mut self.imports.pkgs) {
|
||||||
// Can not be done outside the loop/function because of the borrow checker.
|
// Can not be done outside the loop/function because of the borrow checker.
|
||||||
// Just serves to pass only the import map of the first call to `apply_imports_go`.
|
// Just serves to pass only the import map of the first call to `apply_imports_go`.
|
||||||
@ -162,21 +164,15 @@ impl ParseBook {
|
|||||||
let book = package.to_fun()?;
|
let book = package.to_fun()?;
|
||||||
|
|
||||||
for (name, adt) in new_adts {
|
for (name, adt) in new_adts {
|
||||||
self
|
self.add_imported_adt(name, adt)?;
|
||||||
.add_imported_adt(name, adt)
|
|
||||||
.expect("Package src should be unique, impossible to have name conflicts");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for def in book.defs.into_values() {
|
for def in book.defs.into_values() {
|
||||||
if self.contains_def(&def.name) || self.ctrs.contains_key(&def.name) {
|
self.add_imported_def(def, diag);
|
||||||
unreachable!("Package src should be unique, impossible to have name conflicts");
|
|
||||||
}
|
|
||||||
|
|
||||||
self.fun_defs.insert(def.name.clone(), def);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
diag.fatal(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies a chain of `use bind = src` to every local definition.
|
/// Applies a chain of `use bind = src` to every local definition.
|
||||||
@ -331,27 +327,36 @@ impl ParseBook {
|
|||||||
|
|
||||||
fn add_imported_adt(&mut self, nam: Name, adt: Adt) -> Result<(), String> {
|
fn add_imported_adt(&mut self, nam: Name, adt: Adt) -> Result<(), String> {
|
||||||
if self.adts.get(&nam).is_some() {
|
if self.adts.get(&nam).is_some() {
|
||||||
let err = format!("The imported datatype '{nam}' conflicts with the datatype '{nam}'.");
|
return Err(format!("The datatype '{nam}' conflicts with an imported datatype '{nam}'."));
|
||||||
return Err(err);
|
|
||||||
} else {
|
} else {
|
||||||
for ctr in adt.ctrs.keys() {
|
for ctr in adt.ctrs.keys() {
|
||||||
if self.contains_def(ctr) {
|
if self.contains_def(ctr) {
|
||||||
let err = format!("The imported constructor '{ctr}' conflicts with the definition '{ctr}'.");
|
return Err(format!("The constructor '{ctr}' conflicts with an imported definition '{ctr}'."));
|
||||||
return Err(err);
|
|
||||||
}
|
}
|
||||||
match self.ctrs.entry(ctr.clone()) {
|
match self.ctrs.entry(ctr.clone()) {
|
||||||
Entry::Vacant(e) => _ = e.insert(nam.clone()),
|
Entry::Vacant(e) => _ = e.insert(nam.clone()),
|
||||||
Entry::Occupied(e) => {
|
Entry::Occupied(e) => {
|
||||||
let ctr = e.key();
|
let ctr = e.key();
|
||||||
let err = format!("The imported constructor '{ctr}' conflicts with the constructor '{ctr}'.");
|
return Err(format!("The constructor '{ctr}' conflicts with an imported constructor '{ctr}'."));
|
||||||
return Err(err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.adts.insert(nam, adt);
|
self.adts.insert(nam.clone(), adt);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
fn add_imported_def(&mut self, def: Definition, diag: &mut Diagnostics) {
|
||||||
|
let name = &def.name;
|
||||||
|
if self.contains_def(name) {
|
||||||
|
let err = format!("The definition `{name}` conflicts with an imported definition '{name}'.");
|
||||||
|
diag.add_book_error(err);
|
||||||
|
} else if self.ctrs.contains_key(name) {
|
||||||
|
let err = format!("The definition `{name}` conflicts with an imported constructor '{name}'.");
|
||||||
|
diag.add_book_error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.fun_defs.insert(name.clone(), def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user