From a08c615da4a11bbebe8a689cf784a9ff6cd53810 Mon Sep 17 00:00:00 2001 From: Kasey White Date: Sun, 25 Dec 2022 20:13:58 -0500 Subject: [PATCH] checkpoint --- crates/aiken-lang/src/air.rs | 4 +- crates/aiken-lang/src/builder.rs | 2 +- crates/aiken-lang/src/uplc.rs | 213 +++++++++++++++++++++++++---- crates/uplc/src/ast.rs | 4 + crates/uplc/src/ast/builder.rs | 21 ++- examples/sample/validators/swap.ak | 42 ++++-- 6 files changed, 241 insertions(+), 45 deletions(-) diff --git a/crates/aiken-lang/src/air.rs b/crates/aiken-lang/src/air.rs index c75c128d..ea58ef04 100644 --- a/crates/aiken-lang/src/air.rs +++ b/crates/aiken-lang/src/air.rs @@ -140,8 +140,8 @@ pub enum Air { TupleClause { scope: Vec, tipo: Arc, - indices: HashSet<(u64, String)>, - predefined_indices: HashSet<(u64, String)>, + indices: HashSet<(usize, String)>, + predefined_indices: HashSet<(usize, String)>, subject_name: String, count: usize, complex_clause: bool, diff --git a/crates/aiken-lang/src/builder.rs b/crates/aiken-lang/src/builder.rs index 0335fb68..b4caee4e 100644 --- a/crates/aiken-lang/src/builder.rs +++ b/crates/aiken-lang/src/builder.rs @@ -69,7 +69,7 @@ pub enum ClauseProperties { needs_constr_var: bool, is_complex_clause: bool, original_subject_name: String, - defined_tuple_indices: HashSet<(u64, String)>, + defined_tuple_indices: HashSet<(usize, String)>, }, } diff --git a/crates/aiken-lang/src/uplc.rs b/crates/aiken-lang/src/uplc.rs index c749e28e..fb100e91 100644 --- a/crates/aiken-lang/src/uplc.rs +++ b/crates/aiken-lang/src/uplc.rs @@ -1,12 +1,17 @@ -use std::{collections::HashMap, ops::Deref, sync::Arc, vec}; +use std::{ + collections::{HashMap, HashSet}, + ops::Deref, + sync::Arc, + vec, +}; use indexmap::IndexMap; use itertools::Itertools; use uplc::{ ast::{ builder::{ - self, choose_list, constr_index_exposer, delayed_choose_list, delayed_if_else, if_else, - CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, + self, apply_wrap, choose_list, constr_index_exposer, delayed_choose_list, + delayed_if_else, if_else, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, }, Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType, }, @@ -81,9 +86,11 @@ impl<'a> CodeGenerator<'a> { let scope = vec![self.id_gen.next()]; self.build_ir(&body, &mut ir_stack, scope); + println!("{ir_stack:#?}"); self.define_ir(&mut ir_stack); + println!("{ir_stack:#?}"); let mut term = self.uplc_code_gen(&mut ir_stack); if self.needs_field_access { @@ -113,6 +120,7 @@ impl<'a> CodeGenerator<'a> { version: (1, 0, 0), term, }; + println!("{}", program.to_pretty()); let mut interner = Interner::new(); @@ -772,7 +780,7 @@ impl<'a> CodeGenerator<'a> { pattern, pattern_vec, values, - clause_properties.clone(), + clause_properties, tipo, scope, ); @@ -837,7 +845,7 @@ impl<'a> CodeGenerator<'a> { pattern, pattern_vec, &mut new_vec, - clause_properties.clone(), + clause_properties, tipo, scope, ); @@ -847,7 +855,7 @@ impl<'a> CodeGenerator<'a> { pattern, pattern_vec, &mut vec![], - clause_properties.clone(), + clause_properties, tipo, scope, ); @@ -864,7 +872,7 @@ impl<'a> CodeGenerator<'a> { pattern, pattern_vec, &mut vec![], - clause_properties.clone(), + clause_properties, tipo, scope, ); @@ -879,11 +887,10 @@ impl<'a> CodeGenerator<'a> { pattern: &Pattern>, pattern_vec: &mut Vec, values: &mut Vec, - clause_properties: ClauseProperties, + clause_properties: &mut ClauseProperties, tipo: &Type, scope: Vec, ) { - let mut clause_properties = clause_properties; match pattern { Pattern::Int { .. } => todo!(), Pattern::String { .. } => todo!(), @@ -1011,6 +1018,10 @@ impl<'a> CodeGenerator<'a> { type_map.insert(label, field_type); } + println!("TYPE MAP IS {type_map:#?}"); + println!("Type args are {:#?}", tipo.arg_types()); + println!("ARGUMENTS ARE {:#?}", arguments); + let arguments_index = arguments .iter() .filter_map(|item| { @@ -1023,7 +1034,15 @@ impl<'a> CodeGenerator<'a> { let var_name = self.nested_pattern_ir_and_label( &item.value, &mut nested_pattern, - type_map.get(&label).unwrap(), + type_map.get(&label).unwrap_or( + &Type::App { + public: true, + module: "".to_string(), + name: "Discard".to_string(), + args: vec![], + } + .into(), + ), scope.clone(), ); @@ -1088,7 +1107,83 @@ impl<'a> CodeGenerator<'a> { pattern_vec.append(values); pattern_vec.append(&mut nested_pattern); } - Pattern::Tuple { .. } => todo!(), + Pattern::Tuple { elems, .. } => { + let mut names = vec![]; + let mut nested_pattern = vec![]; + let items_type = &tipo.get_inner_types(); + + for (index, element) in elems.iter().enumerate() { + let name = self.nested_pattern_ir_and_label( + element, + &mut nested_pattern, + &items_type[index], + scope.clone(), + ); + + names.push((name.unwrap_or_else(|| "_".to_string()), index)) + } + let mut defined_indices = match clause_properties.clone() { + ClauseProperties::TupleClause { + defined_tuple_indices, + .. + } => defined_tuple_indices, + _ => unreachable!(), + }; + + let mut previous_defined_names = vec![]; + for (name, index) in names.clone() { + if let Some(defined_index) = defined_indices + .iter() + .find(|(defined_index, _)| *defined_index as usize == index) + { + previous_defined_names.push(defined_index.clone()); + } else { + defined_indices.insert((index, name)); + } + } + println!("DEFINED INDICES ARE {:#?}", defined_indices); + + for (index, name) in previous_defined_names { + let new_name = names + .iter() + .find(|(_, current_index)| *current_index == index) + .map(|(new_name, _)| new_name) + .unwrap(); + + let pattern_type = &tipo.get_inner_types()[index]; + + pattern_vec.push(Air::Lam { + scope: scope.clone(), + name: new_name.clone(), + }); + pattern_vec.push(Air::Var { + scope: scope.clone(), + constructor: ValueConstructor::public( + pattern_type.clone(), + ValueConstructorVariant::LocalVariable { + location: Span::empty(), + }, + ), + name, + variant_name: String::new(), + }); + } + + match clause_properties { + ClauseProperties::TupleClause { + defined_tuple_indices, + .. + } => { + *defined_tuple_indices = defined_indices; + } + _ => unreachable!(), + } + + println!("CLAUSE PROPERTIES IS NOW {:#?}", clause_properties); + + pattern_vec.append(&mut nested_pattern); + pattern_vec.append(values); + } } } @@ -1347,6 +1442,50 @@ impl<'a> CodeGenerator<'a> { Some(constr_var_name) } + a @ Pattern::Tuple { elems, .. } => { + let item_name = format!("__tuple_item_id_{}", self.id_gen.next()); + + let mut clause_properties = ClauseProperties::TupleClause { + clause_var_name: item_name.clone(), + needs_constr_var: false, + is_complex_clause: false, + original_subject_name: item_name.clone(), + defined_tuple_indices: HashSet::new(), + }; + + let mut inner_pattern_vec = vec![]; + + self.when_ir( + a, + &mut inner_pattern_vec, + &mut vec![], + pattern_type, + &mut clause_properties, + scope.clone(), + ); + + let defined_indices = match clause_properties.clone() { + ClauseProperties::TupleClause { + defined_tuple_indices, + .. + } => defined_tuple_indices, + _ => unreachable!(), + }; + + pattern_vec.push(Air::TupleClause { + scope: scope.clone(), + tipo: pattern_type.clone(), + indices: defined_indices, + predefined_indices: HashSet::new(), + subject_name: clause_properties.original_subject_name().to_string(), + count: elems.len(), + complex_clause: false, + }); + + pattern_vec.append(&mut inner_pattern_vec); + + Some(item_name) + } _ => todo!(), } } @@ -3867,7 +4006,7 @@ impl<'a> CodeGenerator<'a> { let current_index = 0; let (first_name, names) = names.split_first().unwrap(); - let head_list = if tipo.is_map() { + let head_list = convert_data_to_type( Term::Apply { function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()) .into(), @@ -3876,23 +4015,9 @@ impl<'a> CodeGenerator<'a> { unique: 0.into(), }) .into(), - } - } else { - convert_data_to_type( - Term::Apply { - function: Term::Force( - Term::Builtin(DefaultFunction::HeadList).into(), - ) - .into(), - argument: Term::Var(Name { - text: format!("__tuple_{}", list_id), - unique: 0.into(), - }) - .into(), - }, - &tipo.get_inner_types()[0], - ) - }; + }, + &tipo.get_inner_types()[0], + ); term = Term::Apply { function: Term::Lambda { @@ -3977,7 +4102,35 @@ impl<'a> CodeGenerator<'a> { arg_stack.push(Term::Error) } } - Air::TupleClause { .. } => todo!(), + Air::TupleClause { + tipo, + indices, + predefined_indices, + subject_name, + complex_clause, + .. + } => { + let term = arg_stack.pop().unwrap(); + + let tuple_types = tipo.get_inner_types(); + + if tuple_types.len() == 2 { + for (index, name) in indices.iter() { + if *index == 0 { + // apply_wrap( + // Term::Builtin(DefaultFunction::FstPair) + // .force_wrap() + // .force_wrap(), + // Term::Var(Name { + // text: subject_name.clone(), + // unique: 0.into(), + // }), + // ) + } + } + } else { + } + } } } } diff --git a/crates/uplc/src/ast.rs b/crates/uplc/src/ast.rs index 8306e1e7..c003252d 100644 --- a/crates/uplc/src/ast.rs +++ b/crates/uplc/src/ast.rs @@ -118,6 +118,10 @@ impl Term { pub fn force_wrap(self) -> Self { Term::Force(self.into()) } + + pub fn delay_wrap(self) -> Self { + Term::Delay(self.into()) + } } impl<'a, T> Display for Term diff --git a/crates/uplc/src/ast/builder.rs b/crates/uplc/src/ast/builder.rs index 7692d8d4..251db3ca 100644 --- a/crates/uplc/src/ast/builder.rs +++ b/crates/uplc/src/ast/builder.rs @@ -6,7 +6,14 @@ pub const CONSTR_FIELDS_EXPOSER: &str = "__constr_fields_exposer"; pub const CONSTR_INDEX_EXPOSER: &str = "__constr_index_exposer"; pub const CONSTR_GET_FIELD: &str = "__constr_get_field"; -pub fn final_wrapper(term: Term) -> Term { +pub fn apply_wrap(function: Term, arg: Term) -> Term { + Term::Apply { + function: function.into(), + argument: arg.into(), + } +} + +pub fn final_wrapper(term: Term) -> Term { Term::Force( Term::Apply { function: Term::Apply { @@ -350,3 +357,15 @@ pub fn choose_list( argument: else_term.into(), } } + +pub fn repeat_tail_list(term: Term, repeat: usize) -> Term { + let mut term = term; + + for _ in 0..repeat { + term = Term::Apply { + function: Term::Builtin(DefaultFunction::TailList).force_wrap().into(), + argument: term.into(), + }; + } + term +} diff --git a/examples/sample/validators/swap.ak b/examples/sample/validators/swap.ak index f85997f8..2a8b53b2 100644 --- a/examples/sample/validators/swap.ak +++ b/examples/sample/validators/swap.ak @@ -12,16 +12,36 @@ pub type Redeemer { msg: ByteArray, } -pub fn spend(datum: Datum, redeemer: Redeemer, context: ScriptContext) -> Bool { +pub type Dummy { + Mannequin { + hands: ByteArray, + feet: Int, + } + Doll { + hands: ByteArray, + datum: Datum, + feet: Int, + } + Puppet { + hands: ByteArray, + dummy: Dummy, + } + Statue { + hands: ByteArray, + boots: ByteArray, + } +} + +pub fn spend(datum: Datum, redeemer: Redeemer, context: Dummy) -> Bool { let must_say_hello = string.from_bytearray(redeemer.msg) == "Hello, World!" + let must_be_signed = #(1, datum, #(redeemer.msg, context )) + // context.transaction.extra_signatories + // |> list.any(fn(vk) { vk == datum.owner }) - let must_be_signed = - context.transaction.extra_signatories - |> list.any(fn(vk) { vk == datum.owner }) - - must_say_hello && must_be_signed -} - -test foo() { - 1 + 1 == 2 -} + when must_be_signed is { + #(a, b, #(c, Mannequin{ feet, ..})) -> feet == 2 + _ -> False + + } + +} \ No newline at end of file