feat: impl infer for new validators
This commit is contained in:
parent
fff90f7df5
commit
1d9034573b
|
@ -489,15 +489,21 @@ If you really meant to return that last expression, try to replace it with the f
|
||||||
name: String,
|
name: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("I found a multi-validator where both take the same number of arguments.\n")]
|
#[error(
|
||||||
#[diagnostic(code("illegal::multi_validator"))]
|
"I stumbled upon an invalid (non-local) clause guard '{}'.\n",
|
||||||
#[diagnostic(help("Multi-validators cannot take the same number of arguments. One must take 3 arguments\nand the other must take 2 arguments. Both of these take {} arguments.", count.to_string().purple()))]
|
name.if_supports_color(Stdout, |s| s.purple())
|
||||||
MultiValidatorEqualArgs {
|
)]
|
||||||
#[label("{} here", count)]
|
#[diagnostic(url(
|
||||||
|
"https://aiken-lang.org/language-tour/control-flow#checking-equality-and-ordering-in-patterns"
|
||||||
|
))]
|
||||||
|
#[diagnostic(code("illegal::clause_guard"))]
|
||||||
|
#[diagnostic(help(
|
||||||
|
"There are some conditions regarding what can be used in a guard. Values must be either local to the function, or defined as module constants. You can't use functions or records in there."
|
||||||
|
))]
|
||||||
|
NonLocalClauseGuardVariable {
|
||||||
|
#[label]
|
||||||
location: Span,
|
location: Span,
|
||||||
#[label("and {} here", count)]
|
name: String,
|
||||||
other_location: Span,
|
|
||||||
count: usize,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("I tripped over an attempt to access elements on something that isn't indexable.\n")]
|
#[error("I tripped over an attempt to access elements on something that isn't indexable.\n")]
|
||||||
|
@ -1021,7 +1027,8 @@ The best thing to do from here is to remove it."#))]
|
||||||
))]
|
))]
|
||||||
IncorrectValidatorArity {
|
IncorrectValidatorArity {
|
||||||
count: u32,
|
count: u32,
|
||||||
#[label("{} arguments", if *count < 2 { "not enough" } else { "too many" })]
|
expected: u32,
|
||||||
|
#[label("{} arguments", if count < expected { "not enough" } else { "too many" })]
|
||||||
location: Span,
|
location: Span,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,9 @@ use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
Annotation, ArgName, ArgVia, DataType, Definition, Function, ModuleConstant, ModuleKind,
|
Annotation, ArgName, ArgVia, DataType, Definition, Function, ModuleConstant, ModuleKind,
|
||||||
RecordConstructor, RecordConstructorArg, Tracing, TypeAlias, TypedArg, TypedDefinition,
|
RecordConstructor, RecordConstructorArg, Tracing, TypeAlias, TypedArg, TypedDefinition,
|
||||||
TypedFunction, TypedModule, UntypedDefinition, UntypedModule, Use, Validator,
|
TypedFunction, TypedModule, UntypedArg, UntypedDefinition, UntypedModule, Use, Validator,
|
||||||
},
|
},
|
||||||
builtins,
|
builtins::{self, fuzzer, generic_var},
|
||||||
builtins::{fuzzer, generic_var},
|
|
||||||
tipo::{expr::infer_function, Span, Type, TypeVar},
|
tipo::{expr::infer_function, Span, Type, TypeVar},
|
||||||
IdGenerator,
|
IdGenerator,
|
||||||
};
|
};
|
||||||
|
@ -172,61 +171,24 @@ fn infer_definition(
|
||||||
doc,
|
doc,
|
||||||
location,
|
location,
|
||||||
end_position,
|
end_position,
|
||||||
mut handlers,
|
handlers,
|
||||||
fallback,
|
mut fallback,
|
||||||
params,
|
params,
|
||||||
name,
|
name,
|
||||||
}) => {
|
}) => {
|
||||||
let params_length = params.len();
|
let params_length = params.len();
|
||||||
|
|
||||||
environment.in_new_scope(|environment| {
|
let mut typed_handlers = vec![];
|
||||||
let preregistered_fn = environment
|
|
||||||
.get_variable(&fun.name)
|
|
||||||
.expect("Could not find preregistered type for function");
|
|
||||||
|
|
||||||
let preregistered_type = preregistered_fn.tipo.clone();
|
for mut handler in handlers {
|
||||||
|
let typed_fun = environment.in_new_scope(|environment| {
|
||||||
|
let temp_params = params.iter().cloned().chain(handler.arguments);
|
||||||
|
handler.arguments = temp_params.collect();
|
||||||
|
|
||||||
let (args_types, _return_type) = preregistered_type
|
put_params_in_scope(&handler.name, environment, ¶ms);
|
||||||
.function_types()
|
|
||||||
.expect("Preregistered type for fn was not a fn");
|
|
||||||
|
|
||||||
for (ix, (arg, t)) in params
|
|
||||||
.iter()
|
|
||||||
.zip(args_types[0..params.len()].iter())
|
|
||||||
.enumerate()
|
|
||||||
{
|
|
||||||
match &arg.arg_name(ix) {
|
|
||||||
ArgName::Named {
|
|
||||||
name,
|
|
||||||
label: _,
|
|
||||||
location: _,
|
|
||||||
} if arg.is_validator_param => {
|
|
||||||
environment.insert_variable(
|
|
||||||
name.to_string(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: arg.location,
|
|
||||||
},
|
|
||||||
t.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
environment.init_usage(
|
|
||||||
name.to_string(),
|
|
||||||
EntityKind::Variable,
|
|
||||||
arg.location,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ArgName::Named { .. } | ArgName::Discarded { .. } => (),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let typed_handlers = vec![];
|
|
||||||
|
|
||||||
for handler in handlers {
|
|
||||||
let temp_params = params.iter().cloned().chain(fun.arguments);
|
|
||||||
fun.arguments = temp_params.collect();
|
|
||||||
|
|
||||||
let mut typed_fun =
|
let mut typed_fun =
|
||||||
infer_function(&fun, module_name, hydrators, environment, lines, tracing)?;
|
infer_function(&handler, module_name, hydrators, environment, tracing)?;
|
||||||
|
|
||||||
if !typed_fun.return_type.is_bool() {
|
if !typed_fun.return_type.is_bool() {
|
||||||
return Err(Error::ValidatorMustReturnBool {
|
return Err(Error::ValidatorMustReturnBool {
|
||||||
|
@ -235,9 +197,13 @@ fn infer_definition(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typed_fun.arguments.drain(0..params_length);
|
||||||
|
|
||||||
|
// TODO: the expected number of args comes from the script purpose
|
||||||
if typed_fun.arguments.len() < 2 || typed_fun.arguments.len() > 3 {
|
if typed_fun.arguments.len() < 2 || typed_fun.arguments.len() > 3 {
|
||||||
return Err(Error::IncorrectValidatorArity {
|
return Err(Error::IncorrectValidatorArity {
|
||||||
count: typed_fun.arguments.len() as u32,
|
count: typed_fun.arguments.len() as u32,
|
||||||
|
expected: 3,
|
||||||
location: typed_fun.location,
|
location: typed_fun.location,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -247,65 +213,61 @@ fn infer_definition(
|
||||||
arg.tipo = builtins::data();
|
arg.tipo = builtins::data();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let params = params.into_iter().chain(other.arguments);
|
Ok(typed_fun)
|
||||||
other.arguments = params.collect();
|
})?;
|
||||||
|
|
||||||
let mut typed_fallback =
|
typed_handlers.push(typed_fun);
|
||||||
infer_function(&other, module_name, hydrators, environment, lines, tracing)?;
|
}
|
||||||
|
|
||||||
if !typed_fallback.return_type.is_bool() {
|
let params = params.into_iter().chain(fallback.arguments);
|
||||||
return Err(Error::ValidatorMustReturnBool {
|
fallback.arguments = params.collect();
|
||||||
return_type: typed_fallback.return_type.clone(),
|
|
||||||
location: typed_fallback.location,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
typed_fallback.arguments.drain(0..params_length);
|
let mut typed_fallback =
|
||||||
|
infer_function(&fallback, module_name, hydrators, environment, tracing)?;
|
||||||
|
|
||||||
if typed_fallback.arguments.len() < 2 || typed_fallback.arguments.len() > 3 {
|
if !typed_fallback.return_type.is_bool() {
|
||||||
return Err(Error::IncorrectValidatorArity {
|
return Err(Error::ValidatorMustReturnBool {
|
||||||
count: typed_fallback.arguments.len() as u32,
|
return_type: typed_fallback.return_type.clone(),
|
||||||
location: typed_fallback.location,
|
location: typed_fallback.location,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if typed_fun.arguments.len() == typed_fallback.arguments.len() {
|
let typed_params = typed_fallback
|
||||||
return Err(Error::MultiValidatorEqualArgs {
|
.arguments
|
||||||
location: typed_fun.location,
|
.drain(0..params_length)
|
||||||
other_location: typed_fallback.location,
|
.map(|mut arg| {
|
||||||
count: typed_fallback.arguments.len(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for arg in typed_fallback.arguments.iter_mut() {
|
|
||||||
if arg.tipo.is_unbound() {
|
if arg.tipo.is_unbound() {
|
||||||
arg.tipo = builtins::data();
|
arg.tipo = builtins::data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arg
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if typed_fallback.arguments.len() != 1 {
|
||||||
|
return Err(Error::IncorrectValidatorArity {
|
||||||
|
count: typed_fallback.arguments.len() as u32,
|
||||||
|
expected: 1,
|
||||||
|
location: typed_fallback.location,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for arg in typed_fallback.arguments.iter_mut() {
|
||||||
|
if arg.tipo.is_unbound() {
|
||||||
|
arg.tipo = builtins::data();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let typed_params = params
|
Ok(Definition::Validator(Validator {
|
||||||
.into_iter()
|
doc,
|
||||||
.map(|mut arg| {
|
end_position,
|
||||||
if arg.tipo.is_unbound() {
|
handlers: typed_handlers,
|
||||||
arg.tipo = builtins::data();
|
fallback: typed_fallback,
|
||||||
}
|
name,
|
||||||
|
location,
|
||||||
arg
|
params: typed_params,
|
||||||
})
|
}))
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(Definition::Validator(Validator {
|
|
||||||
doc,
|
|
||||||
end_position,
|
|
||||||
handlers: typed_handlers,
|
|
||||||
fallback: typed_fallback,
|
|
||||||
name,
|
|
||||||
location,
|
|
||||||
params: typed_params,
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Definition::Test(f) => {
|
Definition::Test(f) => {
|
||||||
|
@ -777,3 +739,40 @@ fn annotate_fuzzer(tipo: &Type, location: &Span) -> Result<Annotation, Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn put_params_in_scope(name: &str, environment: &mut Environment, params: &[UntypedArg]) {
|
||||||
|
let preregistered_fn = environment
|
||||||
|
.get_variable(&name)
|
||||||
|
.expect("Could not find preregistered type for function");
|
||||||
|
|
||||||
|
let preregistered_type = preregistered_fn.tipo.clone();
|
||||||
|
|
||||||
|
let (args_types, _return_type) = preregistered_type
|
||||||
|
.function_types()
|
||||||
|
.expect("Preregistered type for fn was not a fn");
|
||||||
|
|
||||||
|
for (ix, (arg, t)) in params
|
||||||
|
.iter()
|
||||||
|
.zip(args_types[0..params.len()].iter())
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
match &arg.arg_name(ix) {
|
||||||
|
ArgName::Named {
|
||||||
|
name,
|
||||||
|
label: _,
|
||||||
|
location: _,
|
||||||
|
} if arg.is_validator_param => {
|
||||||
|
environment.insert_variable(
|
||||||
|
name.to_string(),
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: arg.location,
|
||||||
|
},
|
||||||
|
t.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
environment.init_usage(name.to_string(), EntityKind::Variable, arg.location);
|
||||||
|
}
|
||||||
|
ArgName::Named { .. } | ArgName::Discarded { .. } => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue