From 542962a2eaa680347daa8f4de67c43185e773081 Mon Sep 17 00:00:00 2001 From: Kasey White Date: Tue, 3 Jan 2023 00:49:09 -0500 Subject: [PATCH] fix: nested list issues in when statements --- crates/aiken-lang/src/air.rs | 10 +- crates/aiken-lang/src/builder.rs | 23 +++- crates/aiken-lang/src/uplc.rs | 198 ++++++++++++------------------- 3 files changed, 108 insertions(+), 123 deletions(-) diff --git a/crates/aiken-lang/src/air.rs b/crates/aiken-lang/src/air.rs index d52fdd78..6bbb9d94 100644 --- a/crates/aiken-lang/src/air.rs +++ b/crates/aiken-lang/src/air.rs @@ -134,7 +134,6 @@ pub enum Air { tail_name: String, next_tail_name: Option, complex_clause: bool, - inverse: bool, }, TupleClause { @@ -153,6 +152,14 @@ pub enum Air { tipo: Arc, }, + ListClauseGuard { + scope: Vec, + tipo: Arc, + tail_name: String, + next_tail_name: Option, + inverse: bool, + }, + Discard { scope: Vec, }, @@ -264,6 +271,7 @@ impl Air { | Air::Clause { scope, .. } | Air::ListClause { scope, .. } | Air::ClauseGuard { scope, .. } + | Air::ListClauseGuard { scope, .. } | Air::Discard { scope } | Air::Finally { scope } | Air::If { scope, .. } diff --git a/crates/aiken-lang/src/builder.rs b/crates/aiken-lang/src/builder.rs index 9f3ef6b7..382f60d6 100644 --- a/crates/aiken-lang/src/builder.rs +++ b/crates/aiken-lang/src/builder.rs @@ -1283,7 +1283,6 @@ pub fn monomorphize( tail_name, complex_clause, next_tail_name, - inverse, } => { if tipo.is_generic() { let mut tipo = tipo.clone(); @@ -1295,7 +1294,6 @@ pub fn monomorphize( tail_name, complex_clause, next_tail_name, - inverse, }; needs_variant = false; } @@ -1317,6 +1315,27 @@ pub fn monomorphize( needs_variant = false; } } + Air::ListClauseGuard { + scope, + tipo, + tail_name, + next_tail_name, + inverse, + } => { + if tipo.is_generic() { + let mut tipo = tipo.clone(); + find_generics_to_replace(&mut tipo, &generic_types); + + new_air[index] = Air::ListClauseGuard { + scope, + tipo, + tail_name, + next_tail_name, + inverse, + }; + needs_variant = false; + } + } Air::RecordAccess { scope, index: record_index, diff --git a/crates/aiken-lang/src/uplc.rs b/crates/aiken-lang/src/uplc.rs index 5458fd26..7fa50c5b 100644 --- a/crates/aiken-lang/src/uplc.rs +++ b/crates/aiken-lang/src/uplc.rs @@ -617,7 +617,6 @@ impl<'a> CodeGenerator<'a> { tail_name: subject_name, next_tail_name: next_tail, complex_clause: *clause_properties.is_complex_clause(), - inverse: false, }); match clause_properties { @@ -758,10 +757,6 @@ impl<'a> CodeGenerator<'a> { } *clause_properties.needs_constr_var() = false; - pattern_vec.push(Air::Discard { - scope: scope.clone(), - }); - self.when_recursive_ir( pattern, pattern_vec, @@ -1191,29 +1186,12 @@ impl<'a> CodeGenerator<'a> { let new_tail_name = "__list_tail".to_string(); if elements.is_empty() { - pattern_vec.push(Air::ListClause { - scope: scope.clone(), + pattern_vec.push(Air::ListClauseGuard { + scope, tipo: pattern_type.clone(), tail_name: item_name.clone(), next_tail_name: None, - complex_clause: false, - inverse: true, - }); - - pattern_vec.push(Air::Discard { - scope: scope.clone(), - }); - - pattern_vec.push(Air::Var { - scope, - constructor: ValueConstructor::public( - pattern_type.clone(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: "__other_clauses_delayed".to_string(), - variant_name: String::new(), + inverse: false, }); } else { for (index, _) in elements.iter().enumerate() { @@ -1241,29 +1219,12 @@ impl<'a> CodeGenerator<'a> { _ => unreachable!(), }; - pattern_vec.push(Air::ListClause { + pattern_vec.push(Air::ListClauseGuard { scope: scope.clone(), tipo: pattern_type.clone(), tail_name: prev_tail_name, next_tail_name: Some(tail_name), - complex_clause: false, - inverse: false, - }); - - pattern_vec.push(Air::Discard { - scope: scope.clone(), - }); - - pattern_vec.push(Air::Var { - scope: scope.clone(), - constructor: ValueConstructor::public( - pattern_type.clone(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: "__other_clauses_delayed".to_string(), - variant_name: "".to_string(), + inverse: true, }); self.when_ir( @@ -1275,54 +1236,20 @@ impl<'a> CodeGenerator<'a> { scope.clone(), ); } else { - pattern_vec.push(Air::ListClause { + pattern_vec.push(Air::ListClauseGuard { scope: scope.clone(), tipo: pattern_type.clone(), tail_name: prev_tail_name, next_tail_name: Some(tail_name.clone()), - complex_clause: false, - inverse: false, + inverse: true, }); - pattern_vec.push(Air::Discard { - scope: scope.clone(), - }); - - pattern_vec.push(Air::Var { - scope: scope.clone(), - constructor: ValueConstructor::public( - pattern_type.clone(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: "__other_clauses_delayed".to_string(), - variant_name: String::new(), - }); - - pattern_vec.push(Air::ListClause { + pattern_vec.push(Air::ListClauseGuard { scope: scope.clone(), tipo: pattern_type.clone(), tail_name: tail_name.clone(), next_tail_name: None, - complex_clause: false, - inverse: true, - }); - - pattern_vec.push(Air::Discard { - scope: scope.clone(), - }); - - pattern_vec.push(Air::Var { - scope: scope.clone(), - constructor: ValueConstructor::public( - pattern_type.clone(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: "__other_clauses_delayed".to_string(), - variant_name: String::new(), + inverse: false, }); self.when_ir( @@ -1341,29 +1268,12 @@ impl<'a> CodeGenerator<'a> { _ => unreachable!(), }; - pattern_vec.push(Air::ListClause { + pattern_vec.push(Air::ListClauseGuard { scope: scope.clone(), tipo: pattern_type.clone(), tail_name: prev_tail_name, next_tail_name: Some(tail_name), - complex_clause: false, - inverse: false, - }); - - pattern_vec.push(Air::Discard { - scope: scope.clone(), - }); - - pattern_vec.push(Air::Var { - scope: scope.clone(), - constructor: ValueConstructor::public( - pattern_type.clone(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: "__other_clauses_delayed".to_string(), - variant_name: "".to_string(), + inverse: true, }); self.when_ir( @@ -3482,7 +3392,6 @@ impl<'a> CodeGenerator<'a> { .into(), argument: Term::Delay(term.into()).into(), } - .force_wrap() } else { term = delayed_if_else( Term::Apply { @@ -3499,26 +3408,11 @@ impl<'a> CodeGenerator<'a> { Air::ListClause { tail_name, next_tail_name, - inverse, complex_clause, .. } => { - // discard to pop off - let _ = arg_stack.pop().unwrap(); - - // the body to be run if the clause matches - // the next branch in the when expression - let (body, mut term) = if inverse { - let term = arg_stack.pop().unwrap(); - let body = arg_stack.pop().unwrap(); - - (body, term) - } else { - let body = arg_stack.pop().unwrap(); - let term = arg_stack.pop().unwrap(); - - (body, term) - }; + let body = arg_stack.pop().unwrap(); + let mut term = arg_stack.pop().unwrap(); let arg = if let Some(next_tail_name) = next_tail_name { Term::Apply { @@ -3619,7 +3513,7 @@ impl<'a> CodeGenerator<'a> { .into(), } } else if tipo.is_list() { - todo!() + unreachable!() } else { Term::Apply { function: DefaultFunction::EqualsInteger.into(), @@ -3646,6 +3540,70 @@ impl<'a> CodeGenerator<'a> { arg_stack.push(term); } + Air::ListClauseGuard { + tail_name, + next_tail_name, + inverse, + .. + } => { + // the body to be run if the clause matches + // the next branch in the when expression + let mut term = arg_stack.pop().unwrap(); + + term = if let Some(next_tail_name) = next_tail_name { + Term::Apply { + function: Term::Lambda { + parameter_name: Name { + text: next_tail_name, + unique: 0.into(), + }, + body: term.into(), + } + .into(), + argument: Term::Apply { + function: Term::Builtin(DefaultFunction::TailList).force_wrap().into(), + argument: Term::Var(Name { + text: tail_name.clone(), + unique: 0.into(), + }) + .into(), + } + .into(), + } + } else { + term + }; + + if !inverse { + term = choose_list( + Term::Var(Name { + text: tail_name, + unique: 0.into(), + }), + Term::Delay(term.into()), + Term::Var(Name { + text: "__other_clauses_delayed".to_string(), + unique: 0.into(), + }), + ) + .force_wrap(); + } else { + term = choose_list( + Term::Var(Name { + text: tail_name, + unique: 0.into(), + }), + Term::Var(Name { + text: "__other_clauses_delayed".to_string(), + unique: 0.into(), + }), + Term::Delay(term.into()), + ) + .force_wrap(); + } + + arg_stack.push(term); + } Air::Finally { .. } => { let _clause = arg_stack.pop().unwrap(); }