arity checking--of local functions
This commit is contained in:
parent
eafe7a7fa9
commit
35e9d0373d
|
@ -167,10 +167,9 @@ pub fn run(src: &'static str) {
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let src = "
|
let src = "
|
||||||
let bar = :bar
|
let bar = :foo
|
||||||
match :foo with {
|
fn foo (foo, bar, ...) -> bar
|
||||||
:foo -> bar
|
foo (42)
|
||||||
}
|
|
||||||
";
|
";
|
||||||
run(src);
|
run(src);
|
||||||
// struct_scalpel::print_dissection_info::<value::Value>()
|
// struct_scalpel::print_dissection_info::<value::Value>()
|
||||||
|
|
|
@ -37,6 +37,13 @@ pub enum FnInfo {
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn match_arities(arities: &HashSet<Arity>, num_args: u8) -> bool {
|
||||||
|
arities.iter().any(|arity| match arity {
|
||||||
|
Arity::Fixed(n) => *n == num_args,
|
||||||
|
Arity::Splat(n) => *n <= num_args,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Validator<'a> {
|
pub struct Validator<'a> {
|
||||||
// TODO: add another term here: FnStatus. See Issue #18.
|
// TODO: add another term here: FnStatus. See Issue #18.
|
||||||
|
@ -269,9 +276,6 @@ impl<'a> Validator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO!
|
// TODO!
|
||||||
// first check all nodes
|
|
||||||
// then...
|
|
||||||
// check arity is 1 if first term is keyword
|
|
||||||
// check arity against fn info if first term is word and second term is args
|
// check arity against fn info if first term is word and second term is args
|
||||||
Synthetic(first, second, rest) => {
|
Synthetic(first, second, rest) => {
|
||||||
match (&first.0, &second.0) {
|
match (&first.0, &second.0) {
|
||||||
|
@ -290,7 +294,7 @@ impl<'a> Validator<'a> {
|
||||||
self.span = *span;
|
self.span = *span;
|
||||||
self.validate();
|
self.validate();
|
||||||
}
|
}
|
||||||
(Ast::Word(_), Ast::Arguments(_)) => {
|
(Ast::Word(name), Ast::Arguments(args)) => {
|
||||||
let (expr, span) = first.as_ref();
|
let (expr, span) = first.as_ref();
|
||||||
self.ast = expr;
|
self.ast = expr;
|
||||||
self.span = *span;
|
self.span = *span;
|
||||||
|
@ -301,7 +305,14 @@ impl<'a> Validator<'a> {
|
||||||
self.span = *span;
|
self.span = *span;
|
||||||
self.validate();
|
self.validate();
|
||||||
|
|
||||||
//TODO: check arity of call
|
//TODO: check arities of prelude fns, too
|
||||||
|
let fn_binding = self.bound(name);
|
||||||
|
if let Some((_, _, FnInfo::Defined(arities, _))) = fn_binding {
|
||||||
|
let num_args = args.len();
|
||||||
|
if !match_arities(arities, num_args as u8) {
|
||||||
|
self.err(format!("arity mismatch: no clause in function `{name}` with {num_args} argument(s)"))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -412,6 +423,8 @@ impl<'a> Validator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: devise a placeholder binding for recursive functions
|
||||||
|
|
||||||
let from = self.status.used_bindings.len();
|
let from = self.status.used_bindings.len();
|
||||||
let mut arities = HashSet::new();
|
let mut arities = HashSet::new();
|
||||||
|
|
||||||
|
@ -588,8 +601,8 @@ impl<'a> Validator<'a> {
|
||||||
self.err("splats in patterns must come last".to_string());
|
self.err("splats in patterns must come last".to_string());
|
||||||
}
|
}
|
||||||
match splatted.as_ref() {
|
match splatted.as_ref() {
|
||||||
(Ast::Placeholder, _) => (),
|
(PlaceholderPattern, _) => (),
|
||||||
(Ast::Word(name), span) => match self.bound(name) {
|
(Word(name), span) => match self.bound(name) {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
self.span = *span;
|
self.span = *span;
|
||||||
self.err(format!("name `{name}` is already bound"))
|
self.err(format!("name `{name}` is already bound"))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user