mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-09-11 11:56:54 +03:00
Merge pull request #651 from HigherOrderCO/636-with-blocks-give-a-false-error-when-the-bind-function-comes-from-an-import
#636 with blocks give a false error when the bind function comes from an import
This commit is contained in:
commit
0b6070e44e
@ -114,6 +114,7 @@ impl ParseBook {
|
||||
let main_imports = main_imports.unwrap_or(&self.import_ctx.map);
|
||||
|
||||
let mut local_imports = BindMap::new();
|
||||
let mut adt_imports = BindMap::new();
|
||||
|
||||
// Collect local imports binds, starting with `__` if not imported by the main book.
|
||||
'outer: for (bind, src) in self.import_ctx.map.binds.iter().rev() {
|
||||
@ -128,7 +129,6 @@ impl ParseBook {
|
||||
|
||||
// Checks if the bind is an loaded ADT name,
|
||||
// If so, add the constructors binds as `bind/ctr` instead.
|
||||
// As ADTs names are not used in the syntax, we don't bind their names.
|
||||
for pkg in self.import_ctx.sources() {
|
||||
if let Some(book) = pkgs.loaded_adts.get(pkg) {
|
||||
if let Some(ctrs) = book.get(&nam) {
|
||||
@ -138,6 +138,8 @@ impl ParseBook {
|
||||
let bind = Name::new(format!("{}{}", bind, ctr_name));
|
||||
local_imports.insert(bind, ctr.clone());
|
||||
}
|
||||
// Add a mapping of the ADT name
|
||||
adt_imports.insert(bind.clone(), nam.clone());
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
@ -149,6 +151,7 @@ impl ParseBook {
|
||||
|
||||
for (_, def) in self.local_defs_mut() {
|
||||
def.apply_binds(true, &local_imports);
|
||||
def.apply_types(&adt_imports);
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,6 +309,8 @@ trait Def {
|
||||
/// and if there are possible constructor names on it, rename rule patterns.
|
||||
fn apply_binds(&mut self, maybe_constructor: bool, binds: &BindMap);
|
||||
|
||||
fn apply_types(&mut self, types: &BindMap);
|
||||
|
||||
fn source(&self) -> &Source;
|
||||
fn source_mut(&mut self) -> &mut Source;
|
||||
fn name_mut(&mut self) -> &mut Name;
|
||||
@ -332,6 +337,22 @@ impl Def for Definition {
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_types(&mut self, types: &BindMap) {
|
||||
fn rename_with_type(bod: &mut Term, types: &BindMap) {
|
||||
if let Term::With { typ, .. } = bod {
|
||||
if let Some(alias) = types.get(typ).cloned() {
|
||||
*typ = alias;
|
||||
}
|
||||
}
|
||||
for child in bod.children_mut() {
|
||||
rename_with_type(child, types);
|
||||
}
|
||||
}
|
||||
for rule in self.rules.iter_mut() {
|
||||
rename_with_type(&mut rule.body, types);
|
||||
}
|
||||
}
|
||||
|
||||
fn source(&self) -> &Source {
|
||||
&self.source
|
||||
}
|
||||
@ -351,6 +372,84 @@ impl Def for imp::Definition {
|
||||
self.body = bod.fold_uses(binds.iter().rev());
|
||||
}
|
||||
|
||||
fn apply_types(&mut self, types: &BindMap) {
|
||||
fn rename_with_type(bod: &mut Stmt, types: &BindMap) {
|
||||
match bod {
|
||||
Stmt::With { typ, bod, nxt } => {
|
||||
if let Some(alias) = types.get(typ).cloned() {
|
||||
*typ = alias
|
||||
}
|
||||
rename_with_type(bod, types);
|
||||
if let Some(nxt) = nxt {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
}
|
||||
Stmt::Assign { nxt, .. } => {
|
||||
if let Some(nxt) = nxt {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
}
|
||||
Stmt::InPlace { nxt, .. } => {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
Stmt::If { then, otherwise, nxt, .. } => {
|
||||
rename_with_type(then, types);
|
||||
rename_with_type(otherwise, types);
|
||||
if let Some(nxt) = nxt {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
}
|
||||
Stmt::Match { arms, nxt, .. } => {
|
||||
for arm in arms {
|
||||
rename_with_type(&mut arm.rgt, types);
|
||||
}
|
||||
if let Some(nxt) = nxt {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
}
|
||||
Stmt::Switch { arms, nxt, .. } => {
|
||||
for arm in arms {
|
||||
rename_with_type(arm, types);
|
||||
}
|
||||
if let Some(nxt) = nxt {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
}
|
||||
Stmt::Bend { step, base, nxt, .. } => {
|
||||
rename_with_type(step, types);
|
||||
rename_with_type(base, types);
|
||||
if let Some(nxt) = nxt {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
}
|
||||
Stmt::Fold { arms, nxt, .. } => {
|
||||
for arm in arms {
|
||||
rename_with_type(&mut arm.rgt, types);
|
||||
}
|
||||
if let Some(nxt) = nxt {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
}
|
||||
Stmt::Ask { nxt, .. } => {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
Stmt::Return { .. } => {}
|
||||
Stmt::Open { nxt, .. } => {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
Stmt::Use { nxt, .. } => {
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
Stmt::LocalDef { def, nxt } => {
|
||||
def.apply_types(types);
|
||||
rename_with_type(nxt, types);
|
||||
}
|
||||
Stmt::Err => {}
|
||||
}
|
||||
}
|
||||
rename_with_type(&mut self.body, types);
|
||||
}
|
||||
|
||||
fn source(&self) -> &Source {
|
||||
&self.source
|
||||
}
|
||||
@ -368,6 +467,8 @@ impl Def for HvmDefinition {
|
||||
/// Do nothing, can not apply binds to a HvmDefinition.
|
||||
fn apply_binds(&mut self, _maybe_constructor: bool, _binds: &BindMap) {}
|
||||
|
||||
fn apply_types(&mut self, _types: &BindMap) {}
|
||||
|
||||
fn source(&self) -> &Source {
|
||||
&self.source
|
||||
}
|
||||
@ -379,6 +480,18 @@ impl Def for HvmDefinition {
|
||||
fn name_mut(&mut self) -> &mut Name {
|
||||
&mut self.name
|
||||
}
|
||||
|
||||
fn canonicalize_name(&mut self, src: &Name, main_imports: &ImportsMap, binds: &mut BindMap) {
|
||||
let def_name = self.name_mut();
|
||||
let mut new_name = Name::new(std::format!("{}/{}", src, def_name));
|
||||
|
||||
if !main_imports.contains_source(&new_name) {
|
||||
new_name = Name::new(std::format!("__{}", new_name));
|
||||
}
|
||||
|
||||
binds.insert(def_name.clone(), new_name.clone());
|
||||
*def_name = new_name;
|
||||
}
|
||||
}
|
||||
|
||||
impl Term {
|
||||
|
7
tests/golden_tests/import_system/import_type.bend
Normal file
7
tests/golden_tests/import_system/import_type.bend
Normal file
@ -0,0 +1,7 @@
|
||||
from lib/MyOption import (MyOption, MyOption/bind, MyOption/wrap)
|
||||
|
||||
def main():
|
||||
with MyOption:
|
||||
a <- MyOption/Some(1)
|
||||
b <- MyOption/Some(2)
|
||||
return wrap((a, b))
|
12
tests/golden_tests/import_system/lib/MyOption.bend
Normal file
12
tests/golden_tests/import_system/lib/MyOption.bend
Normal file
@ -0,0 +1,12 @@
|
||||
type MyOption = (Some val) | (None)
|
||||
|
||||
def MyOption/bind(val, nxt):
|
||||
match val:
|
||||
case MyOption/Some:
|
||||
nxt = undefer(nxt)
|
||||
return nxt(val.val)
|
||||
case MyOption/None:
|
||||
return MyOption/None
|
||||
|
||||
def MyOption/wrap(val):
|
||||
return MyOption/Some(val)
|
5
tests/snapshots/import_system__import_type.bend.snap
Normal file
5
tests/snapshots/import_system__import_type.bend.snap
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/import_system/import_type.bend
|
||||
---
|
||||
λa (a lib/MyOption/MyOption/Some/tag (1, 2))
|
Loading…
Reference in New Issue
Block a user