From dc052bf9b8c853ba91697874dd4a2b922a303ab9 Mon Sep 17 00:00:00 2001 From: Kasey White Date: Fri, 6 Jan 2023 04:11:45 -0500 Subject: [PATCH] fix nested lists without removing discard pop Also fix bool constants created as a data type like in a list start on record update fix: nested list issues in when statements --- crates/aiken-lang/src/air.rs | 15 ++- crates/aiken-lang/src/builder.rs | 65 ++++++--- crates/aiken-lang/src/uplc.rs | 221 +++++++++++++++---------------- 3 files changed, 163 insertions(+), 138 deletions(-) diff --git a/crates/aiken-lang/src/air.rs b/crates/aiken-lang/src/air.rs index d52fdd78..7aca6aec 100644 --- a/crates/aiken-lang/src/air.rs +++ b/crates/aiken-lang/src/air.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc}; use uplc::builtins::DefaultFunction; use crate::{ - ast::{AssignmentKind, BinOp, TypedRecordUpdateArg, UnOp}, + ast::{AssignmentKind, BinOp, UnOp}, tipo::{Type, ValueConstructor}, }; @@ -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, }, @@ -224,8 +231,7 @@ pub enum Air { RecordUpdate { scope: Vec, tipo: Arc, - spread: Box, - args: Vec, + count: usize, }, UnOp { @@ -264,6 +270,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..9dbe3696 100644 --- a/crates/aiken-lang/src/builder.rs +++ b/crates/aiken-lang/src/builder.rs @@ -1038,7 +1038,7 @@ pub fn convert_constants_to_data(constants: Vec) -> Vec UplcConstant::Data(PlutusData::Constr(Constr { - tag: u64::from(b), + tag: convert_constr_to_tag(b.into()), any_constructor: None, fields: vec![], })), @@ -1170,7 +1170,7 @@ pub fn monomorphize( tipo, tail, }; - needs_variant = false; + needs_variant = true; } } Air::ListAccessor { @@ -1189,7 +1189,7 @@ pub fn monomorphize( tipo, tail, }; - needs_variant = false; + needs_variant = true; } } Air::ListExpose { @@ -1208,7 +1208,7 @@ pub fn monomorphize( tipo, tail, }; - needs_variant = false; + needs_variant = true; } } Air::BinOp { @@ -1227,7 +1227,7 @@ pub fn monomorphize( tipo, count, }; - needs_variant = false; + needs_variant = true; } } Air::Builtin { scope, func, tipo } => { @@ -1236,7 +1236,7 @@ pub fn monomorphize( find_generics_to_replace(&mut tipo, &generic_types); new_air[index] = Air::Builtin { scope, func, tipo }; - needs_variant = false; + needs_variant = true; } } // TODO check on assignment if type is needed @@ -1255,7 +1255,7 @@ pub fn monomorphize( subject_name, tipo, }; - needs_variant = false; + needs_variant = true; } } Air::Clause { @@ -1274,7 +1274,7 @@ pub fn monomorphize( subject_name, complex_clause, }; - needs_variant = false; + needs_variant = true; } } Air::ListClause { @@ -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,9 +1294,8 @@ pub fn monomorphize( tail_name, complex_clause, next_tail_name, - inverse, }; - needs_variant = false; + needs_variant = true; } } Air::ClauseGuard { @@ -1314,7 +1312,28 @@ pub fn monomorphize( subject_name, tipo, }; - needs_variant = false; + needs_variant = true; + } + } + 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 = true; } } Air::RecordAccess { @@ -1331,7 +1350,7 @@ pub fn monomorphize( index: record_index, tipo, }; - needs_variant = false; + needs_variant = true; } } Air::FieldsExpose { @@ -1344,7 +1363,7 @@ pub fn monomorphize( if tipo.is_generic() { let mut tipo = tipo.clone(); find_generics_to_replace(&mut tipo, &generic_types); - needs_variant = false; + needs_variant = true; new_indices.push((ind, name, tipo)); } else { new_indices.push((ind, name, tipo)); @@ -1362,7 +1381,7 @@ pub fn monomorphize( find_generics_to_replace(&mut tipo, &generic_types); new_air[index] = Air::Tuple { scope, count, tipo }; - needs_variant = false; + needs_variant = true; } } Air::Todo { scope, label, tipo } => { @@ -1371,17 +1390,25 @@ pub fn monomorphize( find_generics_to_replace(&mut tipo, &generic_types); new_air[index] = Air::Todo { scope, label, tipo }; - needs_variant = false; + needs_variant = true; + } + } + Air::RecordUpdate { scope, tipo, count } => { + if tipo.is_generic() { + let mut tipo = tipo.clone(); + find_generics_to_replace(&mut tipo, &generic_types); + + new_air[index] = Air::RecordUpdate { scope, tipo, count }; + needs_variant = true; } } - Air::RecordUpdate { .. } => todo!(), Air::TupleAccessor { scope, names, tipo } => { if tipo.is_generic() { let mut tipo = tipo.clone(); find_generics_to_replace(&mut tipo, &generic_types); new_air[index] = Air::TupleAccessor { scope, names, tipo }; - needs_variant = false; + needs_variant = true; } } Air::TupleClause { @@ -1406,7 +1433,7 @@ pub fn monomorphize( count, complex_clause, }; - needs_variant = false; + needs_variant = true; } } _ => {} diff --git a/crates/aiken-lang/src/uplc.rs b/crates/aiken-lang/src/uplc.rs index 5458fd26..0d9f1a4b 100644 --- a/crates/aiken-lang/src/uplc.rs +++ b/crates/aiken-lang/src/uplc.rs @@ -477,7 +477,28 @@ impl<'a> CodeGenerator<'a> { tipo: tipo.clone(), }); } - TypedExpr::RecordUpdate { .. } => todo!(), + TypedExpr::RecordUpdate { + tipo, spread, args, .. + } => { + let mut update_ir = vec![]; + let mut spread_scope = scope.clone(); + spread_scope.push(self.id_gen.next()); + + self.build_ir(spread, &mut update_ir, spread_scope); + + for arg in args { + let mut arg_scope = scope.clone(); + arg_scope.push(self.id_gen.next()); + + self.build_ir(&arg.value, &mut update_ir, arg_scope) + } + + ir_stack.push(Air::RecordUpdate { + scope, + tipo: tipo.clone(), + count: args.len(), + }); + } TypedExpr::UnOp { value, op, .. } => { ir_stack.push(Air::UnOp { scope: scope.clone(), @@ -617,7 +638,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 +778,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, @@ -955,7 +971,7 @@ impl<'a> CodeGenerator<'a> { tail_head_names, tail: Some((tail_var, tail_name)), }); - } else { + } else if !elements.is_empty() { pattern_vec.push(Air::ListExpose { scope, tipo: tipo.clone().into(), @@ -1191,30 +1207,15 @@ impl<'a> CodeGenerator<'a> { let new_tail_name = "__list_tail".to_string(); if elements.is_empty() { - pattern_vec.push(Air::ListClause { + pattern_vec.push(Air::ListClauseGuard { scope: scope.clone(), tipo: pattern_type.clone(), tail_name: item_name.clone(), next_tail_name: None, - complex_clause: false, - inverse: true, + inverse: false, }); - 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(), - }); + pattern_vec.push(Air::Discard { scope }); } else { for (index, _) in elements.iter().enumerate() { let prev_tail_name = if index == 0 { @@ -1241,29 +1242,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,37 +1259,11 @@ 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, - }); - - 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 { - scope: scope.clone(), - tipo: pattern_type.clone(), - tail_name: tail_name.clone(), - next_tail_name: None, - complex_clause: false, inverse: true, }); @@ -1313,16 +1271,12 @@ impl<'a> CodeGenerator<'a> { scope: scope.clone(), }); - pattern_vec.push(Air::Var { + pattern_vec.push(Air::ListClauseGuard { scope: scope.clone(), - constructor: ValueConstructor::public( - pattern_type.clone(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: "__other_clauses_delayed".to_string(), - variant_name: String::new(), + tipo: pattern_type.clone(), + tail_name: tail_name.clone(), + next_tail_name: None, + inverse: false, }); self.when_ir( @@ -1341,29 +1295,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 +3419,6 @@ impl<'a> CodeGenerator<'a> { .into(), argument: Term::Delay(term.into()).into(), } - .force_wrap() } else { term = delayed_if_else( Term::Apply { @@ -3499,26 +3435,14 @@ 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 +3543,7 @@ impl<'a> CodeGenerator<'a> { .into(), } } else if tipo.is_list() { - todo!() + unreachable!() } else { Term::Apply { function: DefaultFunction::EqualsInteger.into(), @@ -3646,6 +3570,73 @@ impl<'a> CodeGenerator<'a> { arg_stack.push(term); } + Air::ListClauseGuard { + tail_name, + next_tail_name, + inverse, + .. + } => { + // 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 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(); }