diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4640505a..a0a99974 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
### Changed
+- **aiken-lang**: Fix validator's else handler generation. See [#1015](https://github.com/aiken-lang/aiken/issues/1015) @KtorZ
- **aiken-lang**: Fix underflow in error message reported by the validator arity. See [#1013](https://github.com/aiken-lang/aiken/issues/1013) @KtorZ
- **aiken-lang**: Fix list-pattern needlessly formatting over multiple lines. @KtorZ
- **aiken-lang**: Fix formatter on long alternative patterns spanning over multiple lines. @KtorZ
diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs
index 677dcf17..02675c0e 100644
--- a/crates/aiken-lang/src/ast.rs
+++ b/crates/aiken-lang/src/ast.rs
@@ -714,25 +714,30 @@ impl TypedValidator {
.chain(std::iter::once(&self.fallback).map(|fallback| {
let arg = fallback.arguments.first().unwrap();
- let then = &[
- TypedExpr::let_(
- TypedExpr::local_var(var_context, arg.tipo.clone(), arg.location),
- arg.get_variable_name().map(TypedPattern::var).unwrap_or(
- TypedPattern::Discard {
- name: var_context.to_string(),
- location: arg.location,
- },
+ let then = match arg.get_variable_name() {
+ Some(arg_name) => TypedExpr::sequence(&[
+ TypedExpr::let_(
+ TypedExpr::local_var(
+ var_context,
+ arg.tipo.clone(),
+ arg.location,
+ ),
+ TypedPattern::var(arg_name),
+ arg.tipo.clone(),
+ arg.location,
),
- arg.tipo.clone(),
- arg.location,
- ),
- fallback.body.clone(),
- ];
+ fallback.body.clone(),
+ ]),
+ None => fallback.body.clone(),
+ };
TypedClause {
location: Span::empty(),
- pattern: TypedPattern::var(var_context),
- then: TypedExpr::sequence(then),
+ pattern: TypedPattern::Discard {
+ name: "_".to_string(),
+ location: arg.location,
+ },
+ then,
}
}))
.collect(),
diff --git a/examples/acceptance_tests/script_context/v3/ctx/simple_else/resolved_inputs.template b/examples/acceptance_tests/script_context/v3/ctx/simple_else/resolved_inputs.template
new file mode 100644
index 00000000..9408beef
--- /dev/null
+++ b/examples/acceptance_tests/script_context/v3/ctx/simple_else/resolved_inputs.template
@@ -0,0 +1,6 @@
+[
+ { 0: h'70{{ simple_else.simple_else.else.hash }}'
+ , 1: 1000000000
+ , 2: [1, 24(h'd87980')]
+ }
+]
diff --git a/examples/acceptance_tests/script_context/v3/ctx/simple_else/tx.template b/examples/acceptance_tests/script_context/v3/ctx/simple_else/tx.template
new file mode 100644
index 00000000..ac9168ff
--- /dev/null
+++ b/examples/acceptance_tests/script_context/v3/ctx/simple_else/tx.template
@@ -0,0 +1,33 @@
+[
+ { 0:
+ [ [h'0000000000000000000000000000000000000000000000000000000000000000', 0]
+ ]
+
+ , 1:
+ []
+
+ , 2: 42
+
+ , 11: h'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'
+
+ , 13:
+ [ [h'0000000000000000000000000000000000000000000000000000000000000000', 0]
+ ]
+
+ , 16:
+ [ h'6000000000000000000000000000000000000000000000000000000000', 1000000000
+ ]
+
+ , 17: 1
+ },
+
+ { 5: [[0, 0, 121([]), [1000000, 100000000]]]
+
+ , 7: [h'{{ simple_else.simple_else.else.cbor }}']
+
+ },
+
+ true,
+
+ null
+]
diff --git a/examples/acceptance_tests/script_context/v3/validators/simple_else.ak b/examples/acceptance_tests/script_context/v3/validators/simple_else.ak
new file mode 100644
index 00000000..5183b078
--- /dev/null
+++ b/examples/acceptance_tests/script_context/v3/validators/simple_else.ak
@@ -0,0 +1,95 @@
+use aiken/collection/dict
+use cardano/address.{Address, Script}
+use cardano/assets
+use cardano/script_context.{ScriptContext, Spending}
+use cardano/transaction.{
+ InlineDatum, Input, Output, OutputReference, ScriptPurpose, Spend, Transaction,
+}
+
+validator simple_else {
+ else(ctx: ScriptContext) {
+ expect Spending(output_ref, _) = ctx.info
+
+ let transaction = ctx.transaction
+
+ assert_transaction_id(transaction.id)
+
+ assert_script_info(output_ref)
+
+ assert_inputs(transaction.inputs)
+
+ expect [] = transaction.outputs
+
+ expect [] = transaction.reference_inputs
+
+ expect [] = transaction.extra_signatories
+
+ expect 42 == transaction.fee
+
+ assert_redeemers(transaction.redeemers)
+
+ expect [] == dict.to_pairs(transaction.datums)
+
+ True
+ }
+}
+
+fn assert_transaction_id(id: ByteArray) {
+ expect
+ #"c6fbd346681a8f8337f6b3e51e6ec973f1509367eabc3a44c849af58a1d8471b" == id
+ Void
+}
+
+fn assert_script_info(info: OutputReference) {
+ expect
+ OutputReference {
+ transaction_id: #"0000000000000000000000000000000000000000000000000000000000000000",
+ output_index: 0,
+ } == info
+ Void
+}
+
+fn assert_inputs(inputs: List) {
+ expect [
+ Input {
+ output_reference: OutputReference { transaction_id, output_index: 0 },
+ output: Output {
+ address,
+ value: resolved_input_value,
+ datum: InlineDatum(_),
+ reference_script: None,
+ },
+ },
+ ] = inputs
+
+ expect
+ transaction_id == #"0000000000000000000000000000000000000000000000000000000000000000"
+
+ expect resolved_input_value == assets.from_lovelace(1000000000)
+
+ expect Address { payment_credential: Script(_), stake_credential: None } =
+ address
+
+ Void
+}
+
+fn assert_redeemers(redeemers: Pairs) {
+ expect
+ [
+ Pair(
+ Spend(
+ OutputReference {
+ transaction_id: #"0000000000000000000000000000000000000000000000000000000000000000",
+ output_index: 0,
+ },
+ ),
+ void(),
+ ),
+ ] == redeemers
+ Void
+}
+
+fn void() -> Data {
+ let void: Data = Void
+ void
+}