feat: validator fns no longer need to be public

If the function doesn't match a script purpose
and is unused then it will till present as a
warning.
This commit is contained in:
rvcas 2023-01-15 12:11:16 -05:00 committed by Lucas
parent 63bfb4e05d
commit c66d07a54c
6 changed files with 59 additions and 18 deletions

View File

@ -30,5 +30,11 @@ impl IdGenerator {
}
}
pub const SPEND: &str = "spend";
pub const CERT: &str = "cert";
pub const MINT: &str = "mint";
pub const WITHDRAW: &str = "withdraw";
pub const VALIDATOR_NAMES: [&str; 4] = [SPEND, CERT, MINT, WITHDRAW];
#[cfg(test)]
mod tests;

View File

@ -8,13 +8,13 @@ use itertools::Itertools;
use crate::{
ast::{
Annotation, CallArg, DataType, Definition, Function, ModuleConstant, Pattern,
Annotation, CallArg, DataType, Definition, Function, ModuleConstant, ModuleKind, Pattern,
RecordConstructor, RecordConstructorArg, Span, TypeAlias, TypedDefinition,
UnqualifiedImport, UntypedDefinition, Use, PIPE_VARIABLE,
},
builtins::{self, function, generic_var, tuple, unbound_var},
tipo::fields::FieldMap,
IdGenerator,
IdGenerator, VALIDATOR_NAMES,
};
use super::{
@ -993,6 +993,7 @@ impl<'a> Environment<'a> {
module_name: &String,
hydrators: &mut HashMap<String, Hydrator>,
names: &mut HashMap<&'a str, &'a Span>,
kind: ModuleKind,
) -> Result<(), Error> {
match def {
Definition::Fn(Function {
@ -1051,7 +1052,7 @@ impl<'a> Environment<'a> {
tipo,
);
if !public {
if !public && (kind.is_lib() || !VALIDATOR_NAMES.contains(&name.as_str())) {
self.init_usage(name.clone(), EntityKind::PrivateFunction, *location);
}
}

View File

@ -1389,6 +1389,12 @@ pub enum Warning {
location: Span,
},
#[error("I found a public definition in a validator module.\nDefinitions in validator modules do not need to be public.\n")]
PubInValidatorModule {
#[label]
location: Span,
},
#[error("I found a record update with no fields; effectively updating nothing.\n")]
#[diagnostic(url("https://aiken-lang.org/language-tour/custom-types#record-updates"))]
NoFieldsRecordUpdate {

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use crate::{
ast::{
DataType, Definition, Function, Layer, ModuleConstant, ModuleKind, RecordConstructor,
RecordConstructorArg, TypeAlias, TypedDefinition, TypedModule, UntypedDefinition,
RecordConstructorArg, Span, TypeAlias, TypedDefinition, TypedModule, UntypedDefinition,
UntypedModule, Use,
},
builtins,
@ -57,7 +57,7 @@ impl UntypedModule {
// Register values so they can be used in functions earlier in the module.
for def in self.definitions() {
environment.register_values(def, &name, &mut hydrators, &mut value_names)?;
environment.register_values(def, &name, &mut hydrators, &mut value_names, kind)?;
}
// Infer the types of each definition in the module
@ -79,7 +79,7 @@ impl UntypedModule {
}
for def in consts.into_iter().chain(not_consts) {
let definition = infer_definition(def, &name, &mut hydrators, &mut environment)?;
let definition = infer_definition(def, &name, &mut hydrators, &mut environment, kind)?;
definitions.push(definition);
}
@ -145,6 +145,7 @@ fn infer_definition(
module_name: &String,
hydrators: &mut HashMap<String, Hydrator>,
environment: &mut Environment<'_>,
kind: ModuleKind,
) -> Result<TypedDefinition, Error> {
match def {
Definition::Fn(Function {
@ -158,6 +159,15 @@ fn infer_definition(
end_position,
..
}) => {
if public && kind.is_validator() {
environment.warnings.push(Warning::PubInValidatorModule {
location: Span {
start: location.start,
end: location.start + 3,
},
})
}
let preregistered_fn = environment
.get_variable(&name)
.expect("Could not find preregistered type for function");
@ -239,7 +249,7 @@ fn infer_definition(
Definition::Test(f) => {
if let Definition::Fn(f) =
infer_definition(Definition::Fn(f), module_name, hydrators, environment)?
infer_definition(Definition::Fn(f), module_name, hydrators, environment, kind)?
{
environment.unify(f.return_type.clone(), builtins::bool(), f.location)?;
Ok(Definition::Test(f))
@ -257,6 +267,15 @@ fn infer_definition(
annotation,
..
}) => {
if public && kind.is_validator() {
environment.warnings.push(Warning::PubInValidatorModule {
location: Span {
start: location.start,
end: location.start + 3,
},
})
}
let tipo = environment
.get_type_constructor(&None, &alias, location)
.expect("Could not find existing type for type alias")
@ -284,6 +303,15 @@ fn infer_definition(
constructors: untyped_constructors,
..
}) => {
if public && kind.is_validator() {
environment.warnings.push(Warning::PubInValidatorModule {
location: Span {
start: location.start,
end: location.start + 3,
},
})
}
let constructors = untyped_constructors
.into_iter()
.map(
@ -417,6 +445,15 @@ fn infer_definition(
value,
..
}) => {
if public && kind.is_validator() {
environment.warnings.push(Warning::PubInValidatorModule {
location: Span {
start: location.start,
end: location.start + 3,
},
})
}
let typed_expr = ExprTyper::new(environment).infer_const(&annotation, *value)?;
let tipo = typed_expr.tipo();

View File

@ -17,7 +17,7 @@ use aiken_lang::{
builtins::{self, generic_var},
tipo::TypeInfo,
uplc::CodeGenerator,
IdGenerator,
IdGenerator, CERT, MINT, SPEND, VALIDATOR_NAMES, WITHDRAW,
};
use deps::UseManifest;
use miette::NamedSource;
@ -44,10 +44,7 @@ use uplc::{
use crate::{
config::Config,
error::{Error, Warning},
module::{
CheckedModule, CheckedModules, ParsedModule, ParsedModules, CERT, MINT, SPEND,
VALIDATOR_NAMES, WITHDRAW,
},
module::{CheckedModule, CheckedModules, ParsedModule, ParsedModules},
telemetry::Event,
};

View File

@ -207,12 +207,6 @@ fn find_cycle(
false
}
pub const SPEND: &str = "spend";
pub const CERT: &str = "cert";
pub const MINT: &str = "mint";
pub const WITHDRAW: &str = "withdraw";
pub const VALIDATOR_NAMES: [&str; 4] = [SPEND, CERT, MINT, WITHDRAW];
#[derive(Debug, Clone)]
pub struct CheckedModule {
pub name: String,