feat: new check for valid purpose names
This commit is contained in:
parent
5cf0a4d294
commit
c2c4bddfb3
|
@ -277,6 +277,15 @@ impl TypedFunction {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_valid_purpose_name(&self) -> bool {
|
||||||
|
self.name == PURPOSE_SPEND
|
||||||
|
|| self.name == PURPOSE_PUBLISH
|
||||||
|
|| self.name == PURPOSE_PROPOSE
|
||||||
|
|| self.name == PURPOSE_MINT
|
||||||
|
|| self.name == PURPOSE_WITHDRAW
|
||||||
|
|| self.name == PURPOSE_VOTE
|
||||||
|
}
|
||||||
|
|
||||||
pub fn validator_arity(&self) -> usize {
|
pub fn validator_arity(&self) -> usize {
|
||||||
if self.name == PURPOSE_SPEND
|
if self.name == PURPOSE_SPEND
|
||||||
|| self.name == PURPOSE_PUBLISH
|
|| self.name == PURPOSE_PUBLISH
|
||||||
|
@ -628,6 +637,17 @@ pub struct Validator<T, Arg, Expr> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypedValidator {
|
impl TypedValidator {
|
||||||
|
pub fn available_purposes() -> Vec<String> {
|
||||||
|
vec![
|
||||||
|
PURPOSE_SPEND.to_string(),
|
||||||
|
PURPOSE_MINT.to_string(),
|
||||||
|
PURPOSE_WITHDRAW.to_string(),
|
||||||
|
PURPOSE_PUBLISH.to_string(),
|
||||||
|
PURPOSE_VOTE.to_string(),
|
||||||
|
PURPOSE_PROPOSE.to_string(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
|
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
|
||||||
self.params
|
self.params
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -54,7 +54,7 @@ Validator(
|
||||||
name: "True",
|
name: "True",
|
||||||
},
|
},
|
||||||
doc: None,
|
doc: None,
|
||||||
location: 26..44,
|
location: 20..44,
|
||||||
name: "spend",
|
name: "spend",
|
||||||
public: true,
|
public: true,
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
|
@ -96,7 +96,7 @@ Validator(
|
||||||
name: "True",
|
name: "True",
|
||||||
},
|
},
|
||||||
doc: None,
|
doc: None,
|
||||||
location: 68..79,
|
location: 63..79,
|
||||||
name: "mint",
|
name: "mint",
|
||||||
public: true,
|
public: true,
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
|
|
|
@ -54,7 +54,7 @@ Validator(
|
||||||
name: "True",
|
name: "True",
|
||||||
},
|
},
|
||||||
doc: None,
|
doc: None,
|
||||||
location: 26..44,
|
location: 20..44,
|
||||||
name: "spend",
|
name: "spend",
|
||||||
public: true,
|
public: true,
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
|
@ -96,7 +96,7 @@ Validator(
|
||||||
name: "True",
|
name: "True",
|
||||||
},
|
},
|
||||||
doc: None,
|
doc: None,
|
||||||
location: 68..79,
|
location: 63..79,
|
||||||
name: "mint",
|
name: "mint",
|
||||||
public: true,
|
public: true,
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
|
|
|
@ -54,7 +54,7 @@ Validator(
|
||||||
name: "True",
|
name: "True",
|
||||||
},
|
},
|
||||||
doc: None,
|
doc: None,
|
||||||
location: 26..44,
|
location: 20..44,
|
||||||
name: "spend",
|
name: "spend",
|
||||||
public: true,
|
public: true,
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
|
|
|
@ -23,16 +23,18 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
|
||||||
.then(
|
.then(
|
||||||
select! {Token::Name {name} => name}
|
select! {Token::Name {name} => name}
|
||||||
.then(args_and_body())
|
.then(args_and_body())
|
||||||
.map(|(name, mut function)| {
|
.map_with_span(|(name, mut function), span| {
|
||||||
function.name = name;
|
function.name = name;
|
||||||
|
function.location.start = span.start;
|
||||||
|
|
||||||
function
|
function
|
||||||
})
|
})
|
||||||
.repeated()
|
.repeated()
|
||||||
.then(
|
.then(
|
||||||
just(Token::Else)
|
just(Token::Else)
|
||||||
.ignore_then(args_and_body().map(|mut function| {
|
.ignore_then(args_and_body().map_with_span(|mut function, span| {
|
||||||
function.name = "else".to_string();
|
function.name = "else".to_string();
|
||||||
|
function.location.start = span.start;
|
||||||
|
|
||||||
function
|
function
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
pretty::Documentable,
|
pretty::Documentable,
|
||||||
};
|
};
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
|
use itertools::Itertools;
|
||||||
use miette::{Diagnostic, LabeledSpan};
|
use miette::{Diagnostic, LabeledSpan};
|
||||||
use ordinal::Ordinal;
|
use ordinal::Ordinal;
|
||||||
use owo_colors::{
|
use owo_colors::{
|
||||||
|
@ -1070,6 +1071,21 @@ The best thing to do from here is to remove it."#))]
|
||||||
function: UntypedFunction,
|
function: UntypedFunction,
|
||||||
location: Span,
|
location: Span,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[error("I found a validator handler referring to an unknown purpose.\n")]
|
||||||
|
#[diagnostic(code("unknown::purpose"))]
|
||||||
|
#[diagnostic(help(
|
||||||
|
"Handler must be named after a known purpose. Here is a list of available purposes:\n{}",
|
||||||
|
available_purposes
|
||||||
|
.iter()
|
||||||
|
.map(|p| format!("-> {}", p.if_supports_color(Stdout, |s| s.green())))
|
||||||
|
.join("\n")
|
||||||
|
))]
|
||||||
|
UnknownPurpose {
|
||||||
|
#[label("unknown purpose")]
|
||||||
|
location: Span,
|
||||||
|
available_purposes: Vec<String>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtraData for Error {
|
impl ExtraData for Error {
|
||||||
|
@ -1129,6 +1145,7 @@ impl ExtraData for Error {
|
||||||
| Error::UnexpectedMultiPatternAssignment { .. }
|
| Error::UnexpectedMultiPatternAssignment { .. }
|
||||||
| Error::ExpectOnOpaqueType { .. }
|
| Error::ExpectOnOpaqueType { .. }
|
||||||
| Error::ValidatorMustReturnBool { .. }
|
| Error::ValidatorMustReturnBool { .. }
|
||||||
|
| Error::UnknownPurpose { .. }
|
||||||
| Error::MustInferFirst { .. } => None,
|
| Error::MustInferFirst { .. } => None,
|
||||||
|
|
||||||
Error::UnknownType { name, .. }
|
Error::UnknownType { name, .. }
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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,
|
||||||
TypedModule, UntypedArg, UntypedDefinition, UntypedModule, Use, Validator,
|
TypedModule, TypedValidator, UntypedArg, UntypedDefinition, UntypedModule, Use, Validator,
|
||||||
},
|
},
|
||||||
builtins::{self, fuzzer, generic_var},
|
builtins::{self, fuzzer, generic_var},
|
||||||
tipo::{expr::infer_function, Span, Type, TypeVar},
|
tipo::{expr::infer_function, Span, Type, TypeVar},
|
||||||
|
@ -209,7 +209,15 @@ fn infer_definition(
|
||||||
|
|
||||||
typed_fun.arguments.drain(0..params_length);
|
typed_fun.arguments.drain(0..params_length);
|
||||||
|
|
||||||
// TODO: the expected number of args comes from the script purpose
|
if !typed_fun.has_valid_purpose_name() {
|
||||||
|
return Err(Error::UnknownPurpose {
|
||||||
|
location: typed_fun
|
||||||
|
.location
|
||||||
|
.map(|start, _end| (start, start + typed_fun.name.len())),
|
||||||
|
available_purposes: TypedValidator::available_purposes(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if typed_fun.arguments.len() != typed_fun.validator_arity() {
|
if typed_fun.arguments.len() != typed_fun.validator_arity() {
|
||||||
return Err(Error::IncorrectValidatorArity {
|
return Err(Error::IncorrectValidatorArity {
|
||||||
count: typed_fun.arguments.len() as u32,
|
count: typed_fun.arguments.len() as u32,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
source: crates/aiken-project/src/blueprint/validator.rs
|
source: crates/aiken-project/src/blueprint/validator.rs
|
||||||
description: "Code:\n\nvalidator {\n fn mint(redeemer: Data, ctx: Data) {\n True\n }\n}\n// "
|
description: "Code:\n\nvalidator thing {\n mint(redeemer: Data, policy_id: Data, transaction: Data) {\n True\n }\n}\n// "
|
||||||
---
|
---
|
||||||
{
|
{
|
||||||
"title": "test_module.mint",
|
"title": "test_module.thing_mint",
|
||||||
"redeemer": {
|
"redeemer": {
|
||||||
"title": "redeemer",
|
"title": "redeemer",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/aiken-project/src/blueprint/validator.rs
|
source: crates/aiken-project/src/blueprint/validator.rs
|
||||||
description: "Code:\n\npub opaque type Rational {\n numerator: Int,\n denominator: Int,\n}\n\nvalidator {\n fn opaque_singleton_multi_variants(redeemer: Rational, ctx: Void) {\n True\n }\n}\n"
|
description: "Code:\n\npub opaque type Rational {\n numerator: Int,\n denominator: Int,\n}\n\nvalidator opaque_singleton_multi_variants {\n spend(redeemer: Rational, oref: Data, ctx: Void) {\n True\n }\n}\n"
|
||||||
---
|
---
|
||||||
Schema {
|
Schema {
|
||||||
error: Error {
|
error: Error {
|
||||||
|
@ -16,7 +16,7 @@ Schema {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
location: 117..135,
|
location: 120..138,
|
||||||
source_code: NamedSource {
|
source_code: NamedSource {
|
||||||
name: "",
|
name: "",
|
||||||
source: "<redacted>",
|
source: "<redacted>",
|
||||||
|
|
Loading…
Reference in New Issue