mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-09-11 03:45:29 +03:00
Add unbound refs check
This commit is contained in:
parent
6f6747ddc9
commit
3705094b6d
@ -1,3 +1,4 @@
|
||||
pub mod set_entrypoint;
|
||||
pub mod shared_names;
|
||||
pub mod unbound_refs;
|
||||
pub mod unbound_vars;
|
||||
|
37
src/fun/check/unbound_refs.rs
Normal file
37
src/fun/check/unbound_refs.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use crate::{
|
||||
diagnostics::Diagnostics,
|
||||
fun::{Ctx, Definitions, Name, Term},
|
||||
maybe_grow,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
|
||||
impl Ctx<'_> {
|
||||
pub fn check_unbound_refs(&mut self) -> Result<(), Diagnostics> {
|
||||
self.info.start_pass();
|
||||
for def in self.book.defs.values() {
|
||||
let mut unbounds = HashSet::new();
|
||||
for rule in def.rules.iter() {
|
||||
rule.body.check_unbound_refs(&self.book.defs, &mut unbounds);
|
||||
}
|
||||
for unbound in unbounds {
|
||||
self.info.add_rule_error(format!("Reference to undefined function '{unbound}'"), def.name.clone());
|
||||
}
|
||||
}
|
||||
self.info.fatal(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Term {
|
||||
pub fn check_unbound_refs(&self, defs: &Definitions, unbounds: &mut HashSet<Name>) {
|
||||
maybe_grow(|| {
|
||||
if let Term::Ref { nam } = self {
|
||||
if !defs.contains_key(nam) {
|
||||
unbounds.insert(nam.clone());
|
||||
}
|
||||
}
|
||||
for child in self.children() {
|
||||
child.check_unbound_refs(defs, unbounds);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -36,7 +36,7 @@ impl Ctx<'_> {
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Book {
|
||||
/// The function definitions.
|
||||
pub defs: IndexMap<Name, Definition>,
|
||||
pub defs: Definitions,
|
||||
|
||||
/// The algebraic datatypes defined by the program
|
||||
pub adts: Adts,
|
||||
@ -48,6 +48,7 @@ pub struct Book {
|
||||
pub entrypoint: Option<Name>,
|
||||
}
|
||||
|
||||
pub type Definitions = IndexMap<Name, Definition>;
|
||||
pub type Adts = IndexMap<Name, Adt>;
|
||||
pub type Constructors = IndexMap<Name, Name>;
|
||||
|
||||
|
@ -140,6 +140,8 @@ pub fn desugar_book(
|
||||
ctx.book.float_combinators(MAX_NET_SIZE);
|
||||
}
|
||||
|
||||
ctx.check_unbound_refs()?;
|
||||
|
||||
ctx.prune(opts.prune);
|
||||
|
||||
if opts.merge {
|
||||
|
11
tests/golden_tests/hangs/bad_dup_interaction.bend
Normal file
11
tests/golden_tests/hangs/bad_dup_interaction.bend
Normal file
@ -0,0 +1,11 @@
|
||||
# A net that expands inifinitely like church exponentiation
|
||||
# Compiles to this net:
|
||||
# a
|
||||
# & ({(b c) (d b)} (c d)) ~ {(e a) e}
|
||||
main =
|
||||
let {a1 a2} =
|
||||
@b
|
||||
let {b1 b2} = b
|
||||
let (c1, c2) = b2
|
||||
((b1 c2), c1)
|
||||
(a1 a2)
|
10
tests/golden_tests/run_file/unbound_wrap.bend
Normal file
10
tests/golden_tests/run_file/unbound_wrap.bend
Normal file
@ -0,0 +1,10 @@
|
||||
type Maybe = (Some x) | None
|
||||
|
||||
Maybe/bind val nxt = match val {
|
||||
Maybe/Some: (nxt val.x)
|
||||
Maybe/None: Maybe/None
|
||||
}
|
||||
|
||||
main = with Maybe {
|
||||
(wrap 1)
|
||||
}
|
7
tests/snapshots/run_file__unbound_wrap.bend.snap
Normal file
7
tests/snapshots/run_file__unbound_wrap.bend.snap
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/run_file/unbound_wrap.bend
|
||||
---
|
||||
[4m[1m[31mErrors:[0m
|
||||
[1mIn definition '[4mmain[0m[1m':[0m
|
||||
Reference to undefined function 'Maybe/wrap'
|
Loading…
Reference in New Issue
Block a user