Merge pull request #302 from aiken-lang/when-clause-guards
When clause guards
This commit is contained in:
commit
0e65fecf69
|
@ -807,6 +807,11 @@ pub type TypedClauseGuard = ClauseGuard<Arc<Type>, String>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum ClauseGuard<Type, RecordTag> {
|
pub enum ClauseGuard<Type, RecordTag> {
|
||||||
|
Not {
|
||||||
|
location: Span,
|
||||||
|
value: Box<Self>,
|
||||||
|
},
|
||||||
|
|
||||||
Equals {
|
Equals {
|
||||||
location: Span,
|
location: Span,
|
||||||
left: Box<Self>,
|
left: Box<Self>,
|
||||||
|
@ -861,12 +866,6 @@ pub enum ClauseGuard<Type, RecordTag> {
|
||||||
name: String,
|
name: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
// TupleIndex {
|
|
||||||
// location: Span,
|
|
||||||
// index: u64,
|
|
||||||
// tipo: Type,
|
|
||||||
// tuple: Box<Self>,
|
|
||||||
// },
|
|
||||||
Constant(Constant<Type, RecordTag>),
|
Constant(Constant<Type, RecordTag>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -874,10 +873,10 @@ impl<A, B> ClauseGuard<A, B> {
|
||||||
pub fn location(&self) -> Span {
|
pub fn location(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
ClauseGuard::Constant(constant) => constant.location(),
|
ClauseGuard::Constant(constant) => constant.location(),
|
||||||
ClauseGuard::Or { location, .. }
|
ClauseGuard::Not { location, .. }
|
||||||
|
| ClauseGuard::Or { location, .. }
|
||||||
| ClauseGuard::And { location, .. }
|
| ClauseGuard::And { location, .. }
|
||||||
| ClauseGuard::Var { location, .. }
|
| ClauseGuard::Var { location, .. }
|
||||||
// | ClauseGuard::TupleIndex { location, .. }
|
|
||||||
| ClauseGuard::Equals { location, .. }
|
| ClauseGuard::Equals { location, .. }
|
||||||
| ClauseGuard::NotEquals { location, .. }
|
| ClauseGuard::NotEquals { location, .. }
|
||||||
| ClauseGuard::GtInt { location, .. }
|
| ClauseGuard::GtInt { location, .. }
|
||||||
|
@ -890,17 +889,15 @@ impl<A, B> ClauseGuard<A, B> {
|
||||||
pub fn precedence(&self) -> u8 {
|
pub fn precedence(&self) -> u8 {
|
||||||
// Ensure that this matches the other precedence function for guards
|
// Ensure that this matches the other precedence function for guards
|
||||||
match self {
|
match self {
|
||||||
ClauseGuard::Or { .. } => 1,
|
ClauseGuard::Not { .. } => 1,
|
||||||
ClauseGuard::And { .. } => 2,
|
ClauseGuard::Or { .. } => 2,
|
||||||
|
ClauseGuard::And { .. } => 3,
|
||||||
ClauseGuard::Equals { .. } | ClauseGuard::NotEquals { .. } => 3,
|
ClauseGuard::Equals { .. } | ClauseGuard::NotEquals { .. } => 4,
|
||||||
|
|
||||||
ClauseGuard::GtInt { .. }
|
ClauseGuard::GtInt { .. }
|
||||||
| ClauseGuard::GtEqInt { .. }
|
| ClauseGuard::GtEqInt { .. }
|
||||||
| ClauseGuard::LtInt { .. }
|
| ClauseGuard::LtInt { .. }
|
||||||
| ClauseGuard::LtEqInt { .. } => 4,
|
| ClauseGuard::LtEqInt { .. } => 5,
|
||||||
|
ClauseGuard::Constant(_) | ClauseGuard::Var { .. } => 6,
|
||||||
ClauseGuard::Constant(_) | ClauseGuard::Var { .. } => 5,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -909,10 +906,9 @@ impl TypedClauseGuard {
|
||||||
pub fn tipo(&self) -> Arc<Type> {
|
pub fn tipo(&self) -> Arc<Type> {
|
||||||
match self {
|
match self {
|
||||||
ClauseGuard::Var { tipo, .. } => tipo.clone(),
|
ClauseGuard::Var { tipo, .. } => tipo.clone(),
|
||||||
// ClauseGuard::TupleIndex { type_, .. } => type_.clone(),
|
|
||||||
ClauseGuard::Constant(constant) => constant.tipo(),
|
ClauseGuard::Constant(constant) => constant.tipo(),
|
||||||
|
ClauseGuard::Not { .. }
|
||||||
ClauseGuard::Or { .. }
|
| ClauseGuard::Or { .. }
|
||||||
| ClauseGuard::And { .. }
|
| ClauseGuard::And { .. }
|
||||||
| ClauseGuard::Equals { .. }
|
| ClauseGuard::Equals { .. }
|
||||||
| ClauseGuard::NotEquals { .. }
|
| ClauseGuard::NotEquals { .. }
|
||||||
|
|
|
@ -14,9 +14,12 @@ use uplc::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
air::Air,
|
air::Air,
|
||||||
ast::{AssignmentKind, Clause, Constant, DataType, Pattern, Span, TypedArg, TypedDataType},
|
ast::{
|
||||||
|
AssignmentKind, BinOp, Clause, ClauseGuard, Constant, DataType, Pattern, Span, TypedArg,
|
||||||
|
TypedDataType, UnOp,
|
||||||
|
},
|
||||||
expr::TypedExpr,
|
expr::TypedExpr,
|
||||||
tipo::{PatternConstructor, Type, TypeVar, ValueConstructorVariant},
|
tipo::{PatternConstructor, Type, TypeVar, ValueConstructor, ValueConstructorVariant},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -1707,3 +1710,116 @@ pub fn replace_opaque_type(t: &mut Arc<Type>, data_types: IndexMap<DataTypeKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_clause_guard(
|
||||||
|
clause_guard: &ClauseGuard<Arc<Type>, String>,
|
||||||
|
clause_guard_vec: &mut Vec<Air>,
|
||||||
|
scope: Vec<u64>,
|
||||||
|
) {
|
||||||
|
match clause_guard {
|
||||||
|
ClauseGuard::Not { value, .. } => {
|
||||||
|
clause_guard_vec.push(Air::UnOp {
|
||||||
|
scope: scope.clone(),
|
||||||
|
op: UnOp::Not,
|
||||||
|
});
|
||||||
|
|
||||||
|
handle_clause_guard(value, clause_guard_vec, scope);
|
||||||
|
}
|
||||||
|
ClauseGuard::Equals { left, right, .. } => {
|
||||||
|
clause_guard_vec.push(Air::BinOp {
|
||||||
|
scope: scope.clone(),
|
||||||
|
name: BinOp::Eq,
|
||||||
|
count: 2,
|
||||||
|
tipo: left.tipo(),
|
||||||
|
});
|
||||||
|
handle_clause_guard(left, clause_guard_vec, scope.clone());
|
||||||
|
handle_clause_guard(right, clause_guard_vec, scope);
|
||||||
|
}
|
||||||
|
ClauseGuard::NotEquals { left, right, .. } => {
|
||||||
|
clause_guard_vec.push(Air::BinOp {
|
||||||
|
scope: scope.clone(),
|
||||||
|
name: BinOp::NotEq,
|
||||||
|
count: 2,
|
||||||
|
tipo: left.tipo(),
|
||||||
|
});
|
||||||
|
handle_clause_guard(left, clause_guard_vec, scope.clone());
|
||||||
|
handle_clause_guard(right, clause_guard_vec, scope);
|
||||||
|
}
|
||||||
|
ClauseGuard::GtInt { left, right, .. } => {
|
||||||
|
clause_guard_vec.push(Air::BinOp {
|
||||||
|
scope: scope.clone(),
|
||||||
|
name: BinOp::GtInt,
|
||||||
|
count: 2,
|
||||||
|
tipo: left.tipo(),
|
||||||
|
});
|
||||||
|
handle_clause_guard(left, clause_guard_vec, scope.clone());
|
||||||
|
handle_clause_guard(right, clause_guard_vec, scope);
|
||||||
|
}
|
||||||
|
ClauseGuard::GtEqInt { left, right, .. } => {
|
||||||
|
clause_guard_vec.push(Air::BinOp {
|
||||||
|
scope: scope.clone(),
|
||||||
|
name: BinOp::GtEqInt,
|
||||||
|
count: 2,
|
||||||
|
tipo: left.tipo(),
|
||||||
|
});
|
||||||
|
handle_clause_guard(left, clause_guard_vec, scope.clone());
|
||||||
|
handle_clause_guard(right, clause_guard_vec, scope);
|
||||||
|
}
|
||||||
|
ClauseGuard::LtInt { left, right, .. } => {
|
||||||
|
clause_guard_vec.push(Air::BinOp {
|
||||||
|
scope: scope.clone(),
|
||||||
|
name: BinOp::LtInt,
|
||||||
|
count: 2,
|
||||||
|
tipo: left.tipo(),
|
||||||
|
});
|
||||||
|
handle_clause_guard(left, clause_guard_vec, scope.clone());
|
||||||
|
handle_clause_guard(right, clause_guard_vec, scope);
|
||||||
|
}
|
||||||
|
ClauseGuard::LtEqInt { left, right, .. } => {
|
||||||
|
clause_guard_vec.push(Air::BinOp {
|
||||||
|
scope: scope.clone(),
|
||||||
|
name: BinOp::LtEqInt,
|
||||||
|
count: 2,
|
||||||
|
tipo: left.tipo(),
|
||||||
|
});
|
||||||
|
handle_clause_guard(left, clause_guard_vec, scope.clone());
|
||||||
|
handle_clause_guard(right, clause_guard_vec, scope);
|
||||||
|
}
|
||||||
|
ClauseGuard::Or { left, right, .. } => {
|
||||||
|
clause_guard_vec.push(Air::BinOp {
|
||||||
|
scope: scope.clone(),
|
||||||
|
name: BinOp::Or,
|
||||||
|
count: 2,
|
||||||
|
tipo: left.tipo(),
|
||||||
|
});
|
||||||
|
handle_clause_guard(left, clause_guard_vec, scope.clone());
|
||||||
|
handle_clause_guard(right, clause_guard_vec, scope);
|
||||||
|
}
|
||||||
|
ClauseGuard::And { left, right, .. } => {
|
||||||
|
clause_guard_vec.push(Air::BinOp {
|
||||||
|
scope: scope.clone(),
|
||||||
|
name: BinOp::And,
|
||||||
|
count: 2,
|
||||||
|
tipo: left.tipo(),
|
||||||
|
});
|
||||||
|
handle_clause_guard(left, clause_guard_vec, scope.clone());
|
||||||
|
handle_clause_guard(right, clause_guard_vec, scope);
|
||||||
|
}
|
||||||
|
ClauseGuard::Var { tipo, name, .. } => {
|
||||||
|
clause_guard_vec.push(Air::Var {
|
||||||
|
scope,
|
||||||
|
constructor: ValueConstructor::public(
|
||||||
|
tipo.clone(),
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
name: name.clone(),
|
||||||
|
variant_name: String::new(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ClauseGuard::Constant(constant) => {
|
||||||
|
constants_ir(constant, clause_guard_vec, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1539,6 +1539,9 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
fn clause_guard<'a>(&mut self, clause_guard: &'a UntypedClauseGuard) -> Document<'a> {
|
fn clause_guard<'a>(&mut self, clause_guard: &'a UntypedClauseGuard) -> Document<'a> {
|
||||||
match clause_guard {
|
match clause_guard {
|
||||||
|
ClauseGuard::Not { value, .. } => {
|
||||||
|
docvec!["!", self.clause_guard(value)]
|
||||||
|
}
|
||||||
ClauseGuard::And { left, right, .. } => {
|
ClauseGuard::And { left, right, .. } => {
|
||||||
self.clause_guard_bin_op(" && ", clause_guard.precedence(), left, right)
|
self.clause_guard_bin_op(" && ", clause_guard.precedence(), left, right)
|
||||||
}
|
}
|
||||||
|
|
|
@ -989,9 +989,6 @@ pub fn expr_parser(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: do guards later
|
|
||||||
// let when_clause_guard_parser = just(Token::If);
|
|
||||||
|
|
||||||
let when_clause_parser = pattern_parser()
|
let when_clause_parser = pattern_parser()
|
||||||
.separated_by(just(Token::Comma))
|
.separated_by(just(Token::Comma))
|
||||||
.at_least(1)
|
.at_least(1)
|
||||||
|
@ -1005,20 +1002,29 @@ pub fn expr_parser(
|
||||||
.repeated()
|
.repeated()
|
||||||
.or_not(),
|
.or_not(),
|
||||||
)
|
)
|
||||||
// TODO: do guards later
|
.then(choice((
|
||||||
// .then(when_clause_guard_parser)
|
just(Token::If)
|
||||||
|
.ignore_then(when_clause_guard_parser())
|
||||||
|
.or_not()
|
||||||
|
.then_ignore(just(Token::RArrow)),
|
||||||
|
just(Token::If)
|
||||||
|
.ignore_then(take_until(just(Token::RArrow)))
|
||||||
|
.validate(|_value, span, emit| {
|
||||||
|
emit(ParseError::invalid_when_clause_guard(span));
|
||||||
|
None
|
||||||
|
}),
|
||||||
|
)))
|
||||||
// TODO: add hint "Did you mean to wrap a multi line clause in curly braces?"
|
// TODO: add hint "Did you mean to wrap a multi line clause in curly braces?"
|
||||||
.then_ignore(just(Token::RArrow))
|
|
||||||
.then(r.clone())
|
.then(r.clone())
|
||||||
.map_with_span(|((patterns, alternative_patterns_opt), then), span| {
|
.map_with_span(
|
||||||
ast::UntypedClause {
|
|(((patterns, alternative_patterns_opt), guard), then), span| ast::UntypedClause {
|
||||||
location: span,
|
location: span,
|
||||||
pattern: patterns,
|
pattern: patterns,
|
||||||
alternative_patterns: alternative_patterns_opt.unwrap_or_default(),
|
alternative_patterns: alternative_patterns_opt.unwrap_or_default(),
|
||||||
guard: None,
|
guard,
|
||||||
then,
|
then,
|
||||||
}
|
},
|
||||||
});
|
);
|
||||||
|
|
||||||
let when_parser = just(Token::When)
|
let when_parser = just(Token::When)
|
||||||
// TODO: If subject is empty we should return ParseErrorType::ExpectedExpr,
|
// TODO: If subject is empty we should return ParseErrorType::ExpectedExpr,
|
||||||
|
@ -1373,6 +1379,120 @@ pub fn expr_parser(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn when_clause_guard_parser() -> impl Parser<Token, ast::ClauseGuard<(), ()>, Error = ParseError>
|
||||||
|
{
|
||||||
|
recursive(|r| {
|
||||||
|
let var_parser = select! {
|
||||||
|
Token::Name { name } => name,
|
||||||
|
Token::UpName { name } => name,
|
||||||
|
}
|
||||||
|
.map_with_span(|name, span| ast::ClauseGuard::Var {
|
||||||
|
name,
|
||||||
|
tipo: (),
|
||||||
|
location: span,
|
||||||
|
});
|
||||||
|
|
||||||
|
let constant_parser = constant_value_parser().map(ast::ClauseGuard::Constant);
|
||||||
|
|
||||||
|
let block_parser = r
|
||||||
|
.clone()
|
||||||
|
.delimited_by(just(Token::LeftParen), just(Token::RightParen));
|
||||||
|
|
||||||
|
let leaf_parser = choice((var_parser, constant_parser, block_parser)).boxed();
|
||||||
|
|
||||||
|
let unary_op = just(Token::Bang);
|
||||||
|
|
||||||
|
let unary = unary_op
|
||||||
|
.map_with_span(|op, span| (op, span))
|
||||||
|
.repeated()
|
||||||
|
.then(leaf_parser)
|
||||||
|
.foldr(|(_, span), value| ast::ClauseGuard::Not {
|
||||||
|
location: span.union(value.location()),
|
||||||
|
value: Box::new(value),
|
||||||
|
})
|
||||||
|
.boxed();
|
||||||
|
|
||||||
|
let comparison_op = choice((
|
||||||
|
just(Token::EqualEqual).to(BinOp::Eq),
|
||||||
|
just(Token::NotEqual).to(BinOp::NotEq),
|
||||||
|
just(Token::Less).to(BinOp::LtInt),
|
||||||
|
just(Token::Greater).to(BinOp::GtInt),
|
||||||
|
just(Token::LessEqual).to(BinOp::LtEqInt),
|
||||||
|
just(Token::GreaterEqual).to(BinOp::GtEqInt),
|
||||||
|
));
|
||||||
|
|
||||||
|
let comparison = unary
|
||||||
|
.clone()
|
||||||
|
.then(comparison_op.then(unary).repeated())
|
||||||
|
.foldl(|left, (op, right)| {
|
||||||
|
let location = left.location().union(right.location());
|
||||||
|
let left = Box::new(left);
|
||||||
|
let right = Box::new(right);
|
||||||
|
match op {
|
||||||
|
BinOp::Eq => ast::ClauseGuard::Equals {
|
||||||
|
location,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
BinOp::NotEq => ast::ClauseGuard::NotEquals {
|
||||||
|
location,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
BinOp::LtInt => ast::ClauseGuard::LtInt {
|
||||||
|
location,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
BinOp::GtInt => ast::ClauseGuard::GtInt {
|
||||||
|
location,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
BinOp::LtEqInt => ast::ClauseGuard::LtEqInt {
|
||||||
|
location,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
BinOp::GtEqInt => ast::ClauseGuard::GtEqInt {
|
||||||
|
location,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.boxed();
|
||||||
|
|
||||||
|
let logical_op = choice((
|
||||||
|
just(Token::AmperAmper).to(BinOp::And),
|
||||||
|
just(Token::VbarVbar).to(BinOp::Or),
|
||||||
|
));
|
||||||
|
|
||||||
|
comparison
|
||||||
|
.clone()
|
||||||
|
.then(logical_op.then(comparison).repeated())
|
||||||
|
.foldl(|left, (op, right)| {
|
||||||
|
let location = left.location().union(right.location());
|
||||||
|
let left = Box::new(left);
|
||||||
|
let right = Box::new(right);
|
||||||
|
match op {
|
||||||
|
BinOp::And => ast::ClauseGuard::And {
|
||||||
|
location,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
BinOp::Or => ast::ClauseGuard::Or {
|
||||||
|
location,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> {
|
pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> {
|
||||||
recursive(|r| {
|
recursive(|r| {
|
||||||
choice((
|
choice((
|
||||||
|
|
|
@ -36,6 +36,16 @@ impl ParseError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn invalid_when_clause_guard(span: Span) -> Self {
|
||||||
|
Self {
|
||||||
|
kind: ErrorKind::InvalidWhenClause,
|
||||||
|
span,
|
||||||
|
while_parsing: None,
|
||||||
|
expected: HashSet::new(),
|
||||||
|
label: Some("invalid clause guard"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn malformed_base16_string_literal(span: Span) -> Self {
|
pub fn malformed_base16_string_literal(span: Span) -> Self {
|
||||||
Self {
|
Self {
|
||||||
kind: ErrorKind::MalformedBase16StringLiteral,
|
kind: ErrorKind::MalformedBase16StringLiteral,
|
||||||
|
@ -101,7 +111,7 @@ pub enum ErrorKind {
|
||||||
#[help]
|
#[help]
|
||||||
hint: Option<String>,
|
hint: Option<String>,
|
||||||
},
|
},
|
||||||
#[error("I tripped over a malformed base16-encoded string literal")]
|
#[error("I tripped over a malformed base16-encoded string literal.")]
|
||||||
#[diagnostic(help("{}", formatdoc! {
|
#[diagnostic(help("{}", formatdoc! {
|
||||||
r#"You can declare literal bytearrays from base16-encoded (a.k.a. hexadecimal) string literals.
|
r#"You can declare literal bytearrays from base16-encoded (a.k.a. hexadecimal) string literals.
|
||||||
|
|
||||||
|
@ -113,6 +123,28 @@ pub enum ErrorKind {
|
||||||
"#
|
"#
|
||||||
, "pub const".bright_blue(), "=".yellow(), "\"f4c9f9c4252d86702c2f4c2e49e6648c7cffe3c8f2b6b7d779788f50\"".bright_purple()}))]
|
, "pub const".bright_blue(), "=".yellow(), "\"f4c9f9c4252d86702c2f4c2e49e6648c7cffe3c8f2b6b7d779788f50\"".bright_purple()}))]
|
||||||
MalformedBase16StringLiteral,
|
MalformedBase16StringLiteral,
|
||||||
|
#[error("I failed to understand a when clause guard.")]
|
||||||
|
#[diagnostic(url("https://aiken-lang.org/language-tour/control-flow#checking-equality-and-ordering-in-patterns"))]
|
||||||
|
#[diagnostic(help("{}", formatdoc! {
|
||||||
|
r#"Clause guards are not as capable as standard expressions. While you can combine multiple clauses using '{operator_or}' and '{operator_and}', you can't do any arithmetic in there. They are mainly meant to compare pattern variables to some known constants using simple binary operators.
|
||||||
|
|
||||||
|
For example, the following clauses are well-formed:
|
||||||
|
|
||||||
|
{good} (x, _) if x == 10 -> ...
|
||||||
|
{good} (_, y) if y > 0 && y < 10 -> ...
|
||||||
|
{good} (x, y) if x && (y > 0 || y < 10) -> ...
|
||||||
|
|
||||||
|
However, those aren't:
|
||||||
|
|
||||||
|
{bad} (x, _) if x % 3 == 0 -> ...
|
||||||
|
{bad} (x, y) if x + y > 42 -> ...
|
||||||
|
"#
|
||||||
|
, operator_or = "||".yellow()
|
||||||
|
, operator_and = "&&".yellow()
|
||||||
|
, good = "✔️".green()
|
||||||
|
, bad = "✖️".red()
|
||||||
|
}))]
|
||||||
|
InvalidWhenClause,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Diagnostic, thiserror::Error)]
|
#[derive(Debug, PartialEq, Eq, Hash, Diagnostic, thiserror::Error)]
|
||||||
|
|
|
@ -2128,3 +2128,267 @@ fn subtraction_vs_negate() {
|
||||||
})],
|
})],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn clause_guards() {
|
||||||
|
let code = indoc! {r#"
|
||||||
|
fn foo() {
|
||||||
|
when a is {
|
||||||
|
_ if 42 -> Void
|
||||||
|
_ if bar -> Void
|
||||||
|
_ if True -> Void
|
||||||
|
_ if a || b && c -> Void
|
||||||
|
_ if a || (b && c) -> Void
|
||||||
|
_ if a <= 42 || b > 14 || "str" -> Void
|
||||||
|
_ if a == 14 && !b -> Void
|
||||||
|
_ if !!True -> Void
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#};
|
||||||
|
assert_definitions(
|
||||||
|
code,
|
||||||
|
vec![ast::Definition::Fn(Function {
|
||||||
|
arguments: vec![],
|
||||||
|
body: expr::UntypedExpr::When {
|
||||||
|
location: Span::new((), 13..250),
|
||||||
|
subjects: vec![expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 18..19),
|
||||||
|
name: "a".to_string(),
|
||||||
|
}],
|
||||||
|
clauses: vec![
|
||||||
|
ast::Clause {
|
||||||
|
location: Span::new((), 29..44),
|
||||||
|
pattern: vec![ast::Pattern::Discard {
|
||||||
|
name: "_".to_string(),
|
||||||
|
location: Span::new((), 29..30),
|
||||||
|
}],
|
||||||
|
alternative_patterns: vec![],
|
||||||
|
guard: Some(ast::ClauseGuard::Constant(ast::Constant::Int {
|
||||||
|
location: Span::new((), 34..36),
|
||||||
|
value: "42".to_string(),
|
||||||
|
})),
|
||||||
|
then: expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 40..44),
|
||||||
|
name: "Void".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ast::Clause {
|
||||||
|
location: Span::new((), 49..65),
|
||||||
|
pattern: vec![ast::Pattern::Discard {
|
||||||
|
name: "_".to_string(),
|
||||||
|
location: Span::new((), 49..50),
|
||||||
|
}],
|
||||||
|
alternative_patterns: vec![],
|
||||||
|
guard: Some(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 54..57),
|
||||||
|
name: "bar".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
then: expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 61..65),
|
||||||
|
name: "Void".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ast::Clause {
|
||||||
|
location: Span::new((), 70..87),
|
||||||
|
pattern: vec![ast::Pattern::Discard {
|
||||||
|
name: "_".to_string(),
|
||||||
|
location: Span::new((), 70..71),
|
||||||
|
}],
|
||||||
|
alternative_patterns: vec![],
|
||||||
|
guard: Some(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 75..79),
|
||||||
|
tipo: (),
|
||||||
|
name: "True".to_string(),
|
||||||
|
}),
|
||||||
|
then: expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 83..87),
|
||||||
|
name: "Void".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ast::Clause {
|
||||||
|
location: Span::new((), 92..116),
|
||||||
|
pattern: vec![ast::Pattern::Discard {
|
||||||
|
name: "_".to_string(),
|
||||||
|
location: Span::new((), 92..93),
|
||||||
|
}],
|
||||||
|
alternative_patterns: vec![],
|
||||||
|
guard: Some(ast::ClauseGuard::And {
|
||||||
|
location: Span::new((), 97..108),
|
||||||
|
left: Box::new(ast::ClauseGuard::Or {
|
||||||
|
location: Span::new((), 97..103),
|
||||||
|
left: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 97..98),
|
||||||
|
name: "a".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
right: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 102..103),
|
||||||
|
name: "b".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
right: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 107..108),
|
||||||
|
name: "c".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
then: expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 112..116),
|
||||||
|
name: "Void".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ast::Clause {
|
||||||
|
location: Span::new((), 121..147),
|
||||||
|
pattern: vec![ast::Pattern::Discard {
|
||||||
|
name: "_".to_string(),
|
||||||
|
location: Span::new((), 121..122),
|
||||||
|
}],
|
||||||
|
alternative_patterns: vec![],
|
||||||
|
guard: Some(ast::ClauseGuard::Or {
|
||||||
|
location: Span::new((), 126..138),
|
||||||
|
left: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 126..127),
|
||||||
|
name: "a".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
right: Box::new(ast::ClauseGuard::And {
|
||||||
|
location: Span::new((), 132..138),
|
||||||
|
left: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 132..133),
|
||||||
|
name: "b".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
right: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 137..138),
|
||||||
|
name: "c".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
then: expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 143..147),
|
||||||
|
name: "Void".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ast::Clause {
|
||||||
|
location: Span::new((), 152..191),
|
||||||
|
pattern: vec![ast::Pattern::Discard {
|
||||||
|
name: "_".to_string(),
|
||||||
|
location: Span::new((), 152..153),
|
||||||
|
}],
|
||||||
|
alternative_patterns: vec![],
|
||||||
|
guard: Some(ast::ClauseGuard::Or {
|
||||||
|
location: Span::new((), 157..183),
|
||||||
|
left: Box::new(ast::ClauseGuard::Or {
|
||||||
|
location: Span::new((), 157..174),
|
||||||
|
left: Box::new(ast::ClauseGuard::LtEqInt {
|
||||||
|
location: Span::new((), 157..164),
|
||||||
|
left: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 157..158),
|
||||||
|
name: "a".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
right: Box::new(ast::ClauseGuard::Constant(
|
||||||
|
ast::Constant::Int {
|
||||||
|
location: Span::new((), 162..164),
|
||||||
|
value: "42".to_string(),
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
}),
|
||||||
|
right: Box::new(ast::ClauseGuard::GtInt {
|
||||||
|
location: Span::new((), 168..174),
|
||||||
|
left: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 168..169),
|
||||||
|
name: "b".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
right: Box::new(ast::ClauseGuard::Constant(
|
||||||
|
ast::Constant::Int {
|
||||||
|
location: Span::new((), 172..174),
|
||||||
|
value: "14".to_string(),
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
right: Box::new(ast::ClauseGuard::Constant(ast::Constant::String {
|
||||||
|
location: Span::new((), 178..183),
|
||||||
|
value: "str".to_string(),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
then: expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 187..191),
|
||||||
|
name: "Void".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ast::Clause {
|
||||||
|
location: Span::new((), 196..222),
|
||||||
|
pattern: vec![ast::Pattern::Discard {
|
||||||
|
name: "_".to_string(),
|
||||||
|
location: Span::new((), 196..197),
|
||||||
|
}],
|
||||||
|
alternative_patterns: vec![],
|
||||||
|
guard: Some(ast::ClauseGuard::And {
|
||||||
|
location: Span::new((), 201..214),
|
||||||
|
left: Box::new(ast::ClauseGuard::Equals {
|
||||||
|
location: Span::new((), 201..208),
|
||||||
|
left: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 201..202),
|
||||||
|
name: "a".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
right: Box::new(ast::ClauseGuard::Constant(ast::Constant::Int {
|
||||||
|
location: Span::new((), 206..208),
|
||||||
|
value: "14".to_string(),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
right: Box::new(ast::ClauseGuard::Not {
|
||||||
|
location: Span::new((), 212..214),
|
||||||
|
value: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 213..214),
|
||||||
|
name: "b".to_string(),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
then: expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 218..222),
|
||||||
|
name: "Void".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ast::Clause {
|
||||||
|
location: Span::new((), 227..246),
|
||||||
|
pattern: vec![ast::Pattern::Discard {
|
||||||
|
name: "_".to_string(),
|
||||||
|
location: Span::new((), 227..228),
|
||||||
|
}],
|
||||||
|
alternative_patterns: vec![],
|
||||||
|
guard: Some(ast::ClauseGuard::Not {
|
||||||
|
location: Span::new((), 232..238),
|
||||||
|
value: Box::new(ast::ClauseGuard::Not {
|
||||||
|
location: Span::new((), 233..238),
|
||||||
|
value: Box::new(ast::ClauseGuard::Var {
|
||||||
|
location: Span::new((), 234..238),
|
||||||
|
tipo: (),
|
||||||
|
name: "True".to_string(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
then: expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 242..246),
|
||||||
|
name: "Void".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
doc: None,
|
||||||
|
location: Span::new((), 0..8),
|
||||||
|
name: "foo".to_string(),
|
||||||
|
public: false,
|
||||||
|
return_annotation: None,
|
||||||
|
return_type: (),
|
||||||
|
end_position: 251,
|
||||||
|
})],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1011,41 +1011,17 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClauseGuard::TupleIndex {
|
ClauseGuard::Not {
|
||||||
// location,
|
location, value, ..
|
||||||
// tuple,
|
} => {
|
||||||
// index,
|
let value = self.infer_clause_guard(*value)?;
|
||||||
// ..
|
self.unify(bool(), value.tipo(), value.location())?;
|
||||||
// } => {
|
Ok(ClauseGuard::Not {
|
||||||
// let tuple = self.infer_clause_guard(*tuple)?;
|
location,
|
||||||
// match tuple.type_().as_ref() {
|
value: Box::new(value),
|
||||||
// Type::Tuple { elems } => {
|
})
|
||||||
// let type_ = elems
|
}
|
||||||
// .get(index as usize)
|
|
||||||
// .ok_or(Error::OutOfBoundsTupleIndex {
|
|
||||||
// location,
|
|
||||||
// index,
|
|
||||||
// size: elems.len(),
|
|
||||||
// })?
|
|
||||||
// .clone();
|
|
||||||
// Ok(ClauseGuard::TupleIndex {
|
|
||||||
// location,
|
|
||||||
// index,
|
|
||||||
// type_,
|
|
||||||
// tuple: Box::new(tuple),
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// typ if typ.is_unbound() => Err(Error::NotATupleUnbound {
|
|
||||||
// location: tuple.location(),
|
|
||||||
// }),
|
|
||||||
|
|
||||||
// _ => Err(Error::NotATuple {
|
|
||||||
// location: tuple.location(),
|
|
||||||
// given: tuple.type_(),
|
|
||||||
// }),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
ClauseGuard::And {
|
ClauseGuard::And {
|
||||||
location,
|
location,
|
||||||
left,
|
left,
|
||||||
|
|
|
@ -25,11 +25,12 @@ use crate::{
|
||||||
builder::{
|
builder::{
|
||||||
check_replaceable_opaque_type, check_when_pattern_needs, constants_ir,
|
check_replaceable_opaque_type, check_when_pattern_needs, constants_ir,
|
||||||
convert_constants_to_data, convert_data_to_type, convert_type_to_data, get_common_ancestor,
|
convert_constants_to_data, convert_data_to_type, convert_type_to_data, get_common_ancestor,
|
||||||
get_generics_and_type, handle_func_dependencies_ir, handle_recursion_ir,
|
get_generics_and_type, handle_clause_guard, handle_func_dependencies_ir,
|
||||||
list_access_to_uplc, lookup_data_type_by_tipo, monomorphize, rearrange_clauses,
|
handle_recursion_ir, list_access_to_uplc, lookup_data_type_by_tipo, monomorphize,
|
||||||
replace_opaque_type, wrap_validator_args, AssignmentProperties, ClauseProperties,
|
rearrange_clauses, replace_opaque_type, wrap_validator_args, AssignmentProperties,
|
||||||
DataTypeKey, FuncComponents, FunctionAccessKey,
|
ClauseProperties, DataTypeKey, FuncComponents, FunctionAccessKey,
|
||||||
},
|
},
|
||||||
|
builtins::bool,
|
||||||
expr::TypedExpr,
|
expr::TypedExpr,
|
||||||
tipo::{
|
tipo::{
|
||||||
ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
|
ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
|
||||||
|
@ -665,6 +666,33 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
self.build_ir(&clause.then, &mut clause_then_vec, scope.clone());
|
self.build_ir(&clause.then, &mut clause_then_vec, scope.clone());
|
||||||
|
|
||||||
|
if let Some(clause_guard) = &clause.guard {
|
||||||
|
let mut clause_guard_vec = vec![];
|
||||||
|
*clause_properties.is_complex_clause() = true;
|
||||||
|
let clause_guard_name = format!("__clause_guard_{}", self.id_gen.next());
|
||||||
|
|
||||||
|
clause_guard_vec.push(Air::Let {
|
||||||
|
scope: scope.clone(),
|
||||||
|
name: clause_guard_name.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
|
handle_clause_guard(clause_guard, &mut clause_guard_vec, scope.clone());
|
||||||
|
|
||||||
|
clause_guard_vec.push(Air::ClauseGuard {
|
||||||
|
scope: scope.clone(),
|
||||||
|
subject_name: clause_guard_name,
|
||||||
|
tipo: bool(),
|
||||||
|
});
|
||||||
|
|
||||||
|
clause_guard_vec.push(Air::Bool {
|
||||||
|
scope: scope.clone(),
|
||||||
|
value: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
clause_guard_vec.append(&mut clause_then_vec);
|
||||||
|
clause_then_vec = clause_guard_vec;
|
||||||
|
}
|
||||||
|
|
||||||
match clause_properties {
|
match clause_properties {
|
||||||
ClauseProperties::ConstrClause {
|
ClauseProperties::ConstrClause {
|
||||||
original_subject_name,
|
original_subject_name,
|
||||||
|
@ -4355,7 +4383,47 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
if tipo.is_bool() {
|
if tipo.is_bool() {
|
||||||
|
if complex_clause {
|
||||||
|
let other_clauses = term;
|
||||||
if matches!(clause, Term::Constant(UplcConstant::Bool(true))) {
|
if matches!(clause, Term::Constant(UplcConstant::Bool(true))) {
|
||||||
|
term = if_else(
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
Term::Delay(body.into()),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: "__other_clauses_delayed".to_string(),
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.force_wrap();
|
||||||
|
} else {
|
||||||
|
term = if_else(
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: "__other_clauses_delayed".to_string(),
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
Term::Delay(body.into()),
|
||||||
|
)
|
||||||
|
.force_wrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
term = apply_wrap(
|
||||||
|
Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: "__other_clauses_delayed".to_string(),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: term.into(),
|
||||||
|
},
|
||||||
|
Term::Delay(other_clauses.into()),
|
||||||
|
);
|
||||||
|
} else if matches!(clause, Term::Constant(UplcConstant::Bool(true))) {
|
||||||
term = delayed_if_else(
|
term = delayed_if_else(
|
||||||
Term::Var(Name {
|
Term::Var(Name {
|
||||||
text: subject_name,
|
text: subject_name,
|
||||||
|
@ -5298,6 +5366,21 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let tuple_types = tipo.get_inner_types();
|
let tuple_types = tipo.get_inner_types();
|
||||||
|
|
||||||
|
if complex_clause {
|
||||||
|
let next_clause = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
|
term = apply_wrap(
|
||||||
|
Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: "__other_clauses_delayed".to_string(),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: term.into(),
|
||||||
|
},
|
||||||
|
Term::Delay(next_clause.into()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if tuple_types.len() == 2 {
|
if tuple_types.len() == 2 {
|
||||||
for (index, name) in indices.iter() {
|
for (index, name) in indices.iter() {
|
||||||
if *index == 0 {
|
if *index == 0 {
|
||||||
|
@ -5372,21 +5455,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if complex_clause {
|
|
||||||
let next_clause = arg_stack.pop().unwrap();
|
|
||||||
|
|
||||||
term = apply_wrap(
|
|
||||||
Term::Lambda {
|
|
||||||
parameter_name: Name {
|
|
||||||
text: "__other_clauses_delayed".to_string(),
|
|
||||||
unique: 0.into(),
|
|
||||||
},
|
|
||||||
body: term.into(),
|
|
||||||
},
|
|
||||||
Term::Delay(next_clause.into()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
arg_stack.push(term);
|
arg_stack.push(term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
addr1w8ehrka3eyh8hqxt647qm56z0ju3x8fsyjv2f3cwp5kr5ssvegjnw
|
addr1w8r2ln3c7meykuf6ejw0qu5qtdfxh4e4p68v5e3c0lwmrmsdujvef
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"type": "PlutusScriptV2",
|
"type": "PlutusScriptV2",
|
||||||
"description": "Generated by Aiken",
|
"description": "Generated by Aiken",
|
||||||
"cborHex": "59015159014e01000022253335734646464646466002006464646464646464646600201291010500000000000022323232300600130060013300600100237566601c601e00490011199ab9a0014a09448c94ccd55cf8008a5114a00024464646600a00297adef6c60330050010020022232325333573466e1c005200210031323200137566ae84004c034008d55ce9baa001002223300300200130010012223253335573e002266e9520024bd700991919192999ab9a3371e00c002266e9520003357406e980092f5c0266601001000600c6eb8d55ce8019bab35573c0046ae88008d5d08008011800800911192999aab9f00114a026464a666ae68c01000852889998030030008021aba2002357420020046eb0cc004c008cc004c00800d20004801088c8ccc00400520000032223333573466e1c0100095d0919980200219b8000348008d5d100080091aab9e37540022930b1"
|
"cborHex": "590173590170010000323222253335734646464646466002006464646464646464646600201291010500000000000022323232300600130060013300600100237566601c601e00490011199ab9a0014a09448c94ccd55cf8008a5114a00024464646600a00297adef6c60330050010020022232325333573466e1c005200210031323200137566ae84004c034008d55ce9baa001002223300300200130010012223253335573e002266e9520024bd700991919192999ab9a3371e00c002266e9520003357406e980092f5c0266601001000600c6eb8d55ce8019bab35573c0046ae88008d5d08008011800800911192999aab9f00114a026464a666ae68c01000852889998030030008021aba2002357420020046eb0cc004c008cc004c00800d20004801088c8ccc00400520000032223333573466e1c0100095d0919980200219b8000348008d5d100080091aab9e37540022930b18008009112999aab9f00214984cd5cd98009aba1002333003003357440040021"
|
||||||
}
|
}
|
|
@ -1 +1 @@
|
||||||
59014e01000022253335734646464646466002006464646464646464646600201291010500000000000022323232300600130060013300600100237566601c601e00490011199ab9a0014a09448c94ccd55cf8008a5114a00024464646600a00297adef6c60330050010020022232325333573466e1c005200210031323200137566ae84004c034008d55ce9baa001002223300300200130010012223253335573e002266e9520024bd700991919192999ab9a3371e00c002266e9520003357406e980092f5c0266601001000600c6eb8d55ce8019bab35573c0046ae88008d5d08008011800800911192999aab9f00114a026464a666ae68c01000852889998030030008021aba2002357420020046eb0cc004c008cc004c00800d20004801088c8ccc00400520000032223333573466e1c0100095d0919980200219b8000348008d5d100080091aab9e37540022930b1
|
590170010000323222253335734646464646466002006464646464646464646600201291010500000000000022323232300600130060013300600100237566601c601e00490011199ab9a0014a09448c94ccd55cf8008a5114a00024464646600a00297adef6c60330050010020022232325333573466e1c005200210031323200137566ae84004c034008d55ce9baa001002223300300200130010012223253335573e002266e9520024bd700991919192999ab9a3371e00c002266e9520003357406e980092f5c0266601001000600c6eb8d55ce8019bab35573c0046ae88008d5d08008011800800911192999aab9f00114a026464a666ae68c01000852889998030030008021aba2002357420020046eb0cc004c008cc004c00800d20004801088c8ccc00400520000032223333573466e1c0100095d0919980200219b8000348008d5d100080091aab9e37540022930b18008009112999aab9f00214984cd5cd98009aba1002333003003357440040021
|
|
@ -1 +1 @@
|
||||||
addr_test1wrehrka3eyh8hqxt647qm56z0ju3x8fsyjv2f3cwp5kr5ssh3uwut
|
addr_test1wrr2ln3c7meykuf6ejw0qu5qtdfxh4e4p68v5e3c0lwmrmsk5xskv
|
|
@ -1 +1 @@
|
||||||
addr1w9z47fyj9ffqck2fnld04k27zfe04wq6n9zj76u4ghu4xdcd0futm
|
addr1wyahaesnnh44nkyjj4dv8jk3t4f7frwtzepjyujkk2wjkmczwqttr
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"type": "PlutusScriptV2",
|
"type": "PlutusScriptV2",
|
||||||
"description": "Generated by Aiken",
|
"description": "Generated by Aiken",
|
||||||
"cborHex": "4e4d01000022253335734944526161"
|
"cborHex": "5831582f01000032322225333573494452616300100122253335573e004293099ab9b3001357420046660060066ae880080041"
|
||||||
}
|
}
|
|
@ -1 +1 @@
|
||||||
4d01000022253335734944526161
|
582f01000032322225333573494452616300100122253335573e004293099ab9b3001357420046660060066ae880080041
|
|
@ -1 +1 @@
|
||||||
addr_test1wpz47fyj9ffqck2fnld04k27zfe04wq6n9zj76u4ghu4xdck8aqy7
|
addr_test1wqahaesnnh44nkyjj4dv8jk3t4f7frwtzepjyujkk2wjkmcex5hyx
|
|
@ -0,0 +1 @@
|
||||||
|
addr1w9d2hmr5s8j9cz5xgzjzn3srsfajcwjjzeruaj5mh3kpuqcmvmz3r
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type": "PlutusScriptV2",
|
||||||
|
"description": "Generated by Aiken",
|
||||||
|
"cborHex": "5855585301000032322225333573466e1cc8c0052f7b6301010400010101002323232002375a6aae78008dd69aab9d0010014802052616300100122253335573e004293099ab9b3001357420046660060066ae88008005"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
585301000032322225333573466e1cc8c0052f7b6301010400010101002323232002375a6aae78008dd69aab9d0010014802052616300100122253335573e004293099ab9b3001357420046660060066ae88008005
|
|
@ -0,0 +1 @@
|
||||||
|
addr_test1wpd2hmr5s8j9cz5xgzjzn3srsfajcwjjzeruaj5mh3kpuqcqy077x
|
|
@ -1,9 +1,33 @@
|
||||||
pub fn when_tuple(a: (Int, Int)) -> Int {
|
test foo_1() {
|
||||||
|
let a = False
|
||||||
when a is {
|
when a is {
|
||||||
(a, b) -> a
|
a if a -> False
|
||||||
|
_ -> True
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test when_tuple_1() {
|
test foo_2() {
|
||||||
when_tuple((4, 1)) == 4
|
let point = (14, 42)
|
||||||
|
when point is {
|
||||||
|
(x, _) if x > 100 -> False
|
||||||
|
(x, _) if x > 10 -> True
|
||||||
|
_ -> False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test foo_3() {
|
||||||
|
let point = (14, 42)
|
||||||
|
when point is {
|
||||||
|
(x, y) if x == 14 && y <= 100 -> True
|
||||||
|
_ -> False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test foo_4() {
|
||||||
|
let a = False
|
||||||
|
let point = (14, 42)
|
||||||
|
when point is {
|
||||||
|
(x, y) if !a -> x + y == 56
|
||||||
|
_ -> False
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# This file was generated by Aiken
|
||||||
|
# You typically do not need to edit this file
|
||||||
|
|
||||||
|
requirements = []
|
||||||
|
packages = []
|
|
@ -0,0 +1,3 @@
|
||||||
|
name = 'aiken-lang/acceptance_test_049'
|
||||||
|
version = '0.0.0'
|
||||||
|
description = ''
|
|
@ -0,0 +1 @@
|
||||||
|
addr1w9z47fyj9ffqck2fnld04k27zfe04wq6n9zj76u4ghu4xdcd0futm
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type": "PlutusScriptV2",
|
||||||
|
"description": "Generated by Aiken",
|
||||||
|
"cborHex": "4e4d01000022253335734944526161"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
4d01000022253335734944526161
|
|
@ -0,0 +1 @@
|
||||||
|
addr_test1wpz47fyj9ffqck2fnld04k27zfe04wq6n9zj76u4ghu4xdck8aqy7
|
|
@ -0,0 +1,9 @@
|
||||||
|
pub fn when_tuple(a: (Int, Int)) -> Int {
|
||||||
|
when a is {
|
||||||
|
(a, b) -> a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test when_tuple_1() {
|
||||||
|
when_tuple((4, 1)) == 4
|
||||||
|
}
|
Loading…
Reference in New Issue