From d05d8e7de689a2be4914f1d24d874cd6e491e04e Mon Sep 17 00:00:00 2001 From: microproofs Date: Fri, 1 Mar 2024 13:22:02 -0500 Subject: [PATCH] Start working on separating pairs from 2 tuples in Aiken co-authored-by: KtorZ --- crates/aiken-lang/src/builtins.rs | 4 ++ crates/aiken-lang/src/gen_uplc.rs | 51 +++++++++-------- crates/aiken-lang/src/gen_uplc/builder.rs | 12 ++-- crates/aiken-lang/src/tipo.rs | 57 +++++++++++-------- crates/aiken-lang/src/tipo/environment.rs | 6 ++ crates/aiken-lang/src/tipo/pretty.rs | 3 + .../src/blueprint/definitions.rs | 7 +++ crates/aiken-project/src/blueprint/schema.rs | 1 + 8 files changed, 89 insertions(+), 52 deletions(-) diff --git a/crates/aiken-lang/src/builtins.rs b/crates/aiken-lang/src/builtins.rs index 6b18f941..90bda4fc 100644 --- a/crates/aiken-lang/src/builtins.rs +++ b/crates/aiken-lang/src/builtins.rs @@ -1334,6 +1334,10 @@ pub fn tuple(elems: Vec>) -> Rc { Rc::new(Type::Tuple { elems, alias: None }) } +pub fn pair(fst: Rc, snd: Rc) -> Rc { + Rc::new(Type::Pair { fst, snd }) +} + pub fn bool() -> Rc { Rc::new(Type::App { args: vec![], diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 4c45ff81..e1e442e0 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -762,7 +762,7 @@ impl<'a> CodeGenerator<'a> { TypedExpr::TupleIndex { index, tuple, tipo, .. } => { - if tuple.tipo().is_2_tuple() { + if tuple.tipo().is_pair() { AirTree::pair_index( *index, tipo.clone(), @@ -1486,7 +1486,7 @@ impl<'a> CodeGenerator<'a> { AirTree::let_assignment(&list_name, value, func_call) } - } else if tipo.is_2_tuple() { + } else if tipo.is_pair() { let tuple_inner_types = tipo.get_inner_types(); assert!(tuple_inner_types.len() == 2); @@ -3833,7 +3833,7 @@ impl<'a> CodeGenerator<'a> { } DefaultFunction::HeadList - if !constructor.tipo.return_type().unwrap().is_2_tuple() => + if !constructor.tipo.return_type().unwrap().is_pair() => { builder::undata_builtin( builtin, @@ -4249,7 +4249,7 @@ impl<'a> CodeGenerator<'a> { builder::undata_builtin(&func, count, tipo, arg_vec) } - DefaultFunction::HeadList if !tipo.is_2_tuple() => { + DefaultFunction::HeadList if !tipo.is_pair() => { builder::undata_builtin(&func, count, tipo, arg_vec) } @@ -4310,15 +4310,14 @@ impl<'a> CodeGenerator<'a> { ); return Some(term); - } else if tipo.is_map() { + } + if tipo.is_map() { let term = builtin .apply(Term::map_data().apply(left)) .apply(Term::map_data().apply(right)); - return Some(term); - } else if tipo.is_tuple() - && matches!(tipo.get_uplc_type(), UplcType::Pair(_, _)) - { + } + if tipo.is_pair() { let term = builtin .apply(Term::map_data().apply( Term::mk_cons().apply(left).apply(Term::empty_map()), @@ -4326,15 +4325,16 @@ impl<'a> CodeGenerator<'a> { .apply(Term::map_data().apply( Term::mk_cons().apply(right).apply(Term::empty_map()), )); - return Some(term); - } else if tipo.is_list() || tipo.is_tuple() { + } + if tipo.is_list() || tipo.is_tuple() { let term = builtin .apply(Term::list_data().apply(left)) .apply(Term::list_data().apply(right)); return Some(term); - } else if tipo.is_void() { + } + if tipo.is_void() { let term = left.choose_unit(right.choose_unit(Term::bool(true))); return Some(term); @@ -4352,16 +4352,16 @@ impl<'a> CodeGenerator<'a> { ); return Some(term); - } else if tipo.is_map() { + } + if tipo.is_map() { let term = builtin .apply(Term::map_data().apply(left)) .apply(Term::map_data().apply(right)) .if_then_else(Term::bool(false), Term::bool(true)); return Some(term); - } else if tipo.is_tuple() - && matches!(tipo.get_uplc_type(), UplcType::Pair(_, _)) - { + } + if tipo.is_pair() { let term = builtin .apply(Term::map_data().apply( Term::mk_cons().apply(left).apply(Term::empty_map()), @@ -4370,16 +4370,16 @@ impl<'a> CodeGenerator<'a> { Term::mk_cons().apply(right).apply(Term::empty_map()), )) .if_then_else(Term::bool(false), Term::bool(true)); - return Some(term); - } else if tipo.is_list() || tipo.is_tuple() { + } + if tipo.is_list() || tipo.is_tuple() { let term = builtin .apply(Term::list_data().apply(left)) .apply(Term::list_data().apply(right)) .if_then_else(Term::bool(false), Term::bool(true)); - return Some(term); - } else if tipo.is_void() { + } + if tipo.is_void() { return Some(Term::bool(false)); } @@ -4642,9 +4642,14 @@ impl<'a> CodeGenerator<'a> { || tipo.is_string() || tipo.is_list() || tipo.is_tuple() + || tipo.is_pair() || tipo.is_bool() + || tipo.is_bls381_12_g1() + || tipo.is_bls381_12_g2() { subject + } else if tipo.is_ml_result() { + unreachable!() } else { Term::var( self.special_functions @@ -4709,7 +4714,7 @@ impl<'a> CodeGenerator<'a> { Term::equals_string() .apply(clause) .apply(Term::var(subject_name)) - } else if tipo.is_list() || tipo.is_tuple() { + } else if tipo.is_list() || tipo.is_tuple() || tipo.is_pair() { unreachable!("{:#?}", tipo) } else { Term::equals_integer() @@ -4787,7 +4792,7 @@ impl<'a> CodeGenerator<'a> { .apply(next_clause.delay()); } - if tipo.is_2_tuple() { + if tipo.is_pair() { for (index, name) in indices.iter() { if name == "_" { continue; @@ -5256,7 +5261,7 @@ impl<'a> CodeGenerator<'a> { let mut term = arg_stack.pop().unwrap(); let list_id = self.id_gen.next(); - if tipo.is_2_tuple() { + if tipo.is_pair() { assert!(names.len() == 2); if names[1] != "_" { diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index 519ce5fc..0272a877 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -112,7 +112,7 @@ impl ClauseProperties { checked_index: -1, }, } - } else if t.is_tuple() { + } else if t.is_tuple() || t.is_pair() { ClauseProperties { clause_var_name: constr_var, complex_clause: false, @@ -154,7 +154,7 @@ impl ClauseProperties { checked_index: -1, }, } - } else if t.is_tuple() { + } else if t.is_tuple() || t.is_pair() { ClauseProperties { clause_var_name: constr_var, complex_clause: false, @@ -356,7 +356,7 @@ pub fn get_generic_variant_name(t: &Rc) -> String { "_ml_result".to_string() } else if t.is_map() { "_map".to_string() - } else if t.is_2_tuple() { + } else if t.is_pair() { "_pair".to_string() } else if t.is_list() { "_list".to_string() @@ -941,7 +941,7 @@ pub fn known_data_to_type(term: Term, field_type: &Type) -> Term { Term::unmap_data().apply(term) } else if field_type.is_string() { Term::Builtin(DefaultFunction::DecodeUtf8).apply(Term::un_b_data().apply(term)) - } else if field_type.is_tuple() && matches!(field_type.get_uplc_type(), UplcType::Pair(_, _)) { + } else if field_type.is_pair() { Term::mk_pair_data() .apply(Term::head_list().apply(Term::var("__list_data"))) .apply(Term::head_list().apply(Term::tail_list().apply(Term::var("__list_data")))) @@ -1098,7 +1098,7 @@ pub fn unknown_data_to_type_debug( ) .lambda("__val") .apply(term) - } else if field_type.is_tuple() && matches!(field_type.get_uplc_type(), UplcType::Pair(_, _)) { + } else if field_type.is_pair() { Term::var("__val") .delayed_choose_data( error_term.clone(), @@ -1313,7 +1313,7 @@ pub fn convert_type_to_data(term: Term, field_type: &Rc) -> Term>, alias: Option>, }, + + Pair { + fst: Rc, + snd: Rc, + }, } impl PartialEq for Type { @@ -208,6 +213,7 @@ impl Type { } => *opaque || args.iter().any(|arg| arg.contains_opaque()), Type::Tuple { elems, .. } => elems.iter().any(|elem| elem.contains_opaque()), Type::Fn { .. } => false, + Type::Pair { fst, snd } => fst.contains_opaque() || snd.contains_opaque(), } } @@ -218,7 +224,7 @@ impl Type { } => { *contains_opaque = opaque; } - Type::Fn { .. } | Type::Var { .. } | Type::Tuple { .. } => (), + Type::Fn { .. } | Type::Var { .. } | Type::Tuple { .. } | Type::Pair { .. } => (), } } @@ -343,24 +349,24 @@ impl Type { } if "List" == name && module.is_empty() => args .first() .expect("unreachable: List should have an inner type") - .is_2_tuple(), - Self::Var { tipo, .. } => tipo.borrow().is_map(), + .is_pair(), + Self::Var { tipo } => tipo.borrow().is_map(), _ => false, } } pub fn is_tuple(&self) -> bool { match self { - Type::Var { tipo, .. } => tipo.borrow().is_tuple(), - Type::Tuple { .. } => true, + Self::Var { tipo } => tipo.borrow().is_tuple(), + Self::Tuple { .. } => true, _ => false, } } - pub fn is_2_tuple(&self) -> bool { + pub fn is_pair(&self) -> bool { match self { - Type::Var { tipo, .. } => tipo.borrow().is_2_tuple(), - Type::Tuple { elems, .. } => elems.len() == 2, + Self::Var { tipo } => tipo.borrow().is_pair(), + Self::Pair { .. } => true, _ => false, } } @@ -375,7 +381,7 @@ impl Type { pub fn is_generic(&self) -> bool { match self { - Type::App { args, .. } => { + Self::App { args, .. } => { let mut is_a_generic = false; for arg in args { is_a_generic = is_a_generic || arg.is_generic(); @@ -383,21 +389,22 @@ impl Type { is_a_generic } - Type::Var { tipo, .. } => tipo.borrow().is_generic(), - Type::Tuple { elems, .. } => { + Self::Var { tipo } => tipo.borrow().is_generic(), + Self::Tuple { elems } => { let mut is_a_generic = false; for elem in elems { is_a_generic = is_a_generic || elem.is_generic(); } is_a_generic } - Type::Fn { args, ret, .. } => { + Self::Fn { args, ret } => { let mut is_a_generic = false; for arg in args { is_a_generic = is_a_generic || arg.is_generic(); } is_a_generic || ret.is_generic() } + Self::Pair { fst, snd } => fst.is_generic() || snd.is_generic(), } } @@ -412,7 +419,7 @@ impl Type { pub fn get_generic(&self) -> Option { match self { - Type::Var { tipo, .. } => tipo.borrow().get_generic(), + Self::Var { tipo } => tipo.borrow().get_generic(), _ => None, } } @@ -446,6 +453,7 @@ impl Type { } } + // TODO: THIS WILL CHANGE DUE TO PAIRS pub fn get_uplc_type(&self) -> UplcType { if self.is_int() { UplcType::Integer @@ -461,16 +469,12 @@ impl Type { UplcType::List(UplcType::Data.into()) } else if self.is_tuple() { match self { - Self::Tuple { elems, .. } => { - if elems.len() == 2 { - UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()) - } else { - UplcType::List(UplcType::Data.into()) - } - } - Self::Var { tipo, .. } => tipo.borrow().get_uplc_type().unwrap(), + Self::Tuple { .. } => UplcType::List(UplcType::Data.into()), + Self::Var { tipo } => tipo.borrow().get_uplc_type().unwrap(), _ => unreachable!(), } + } else if self.is_pair() { + UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()) } else if self.is_bls381_12_g1() { UplcType::Bls12_381G1Element } else if self.is_bls381_12_g2() { @@ -559,6 +563,13 @@ impl Type { TypeVar::Link { tipo, .. } => tipo.find_private_type(), }, + Self::Pair { fst, snd } => { + if let Some(private_type) = fst.find_private_type() { + Some(private_type) + } else { + snd.find_private_type() + } + } } } @@ -955,9 +966,9 @@ impl TypeVar { } } - pub fn is_2_tuple(&self) -> bool { + pub fn is_pair(&self) -> bool { match self { - Self::Link { tipo } => tipo.is_2_tuple(), + Self::Link { tipo } => tipo.is_pair(), _ => false, } } diff --git a/crates/aiken-lang/src/tipo/environment.rs b/crates/aiken-lang/src/tipo/environment.rs index 9f49c871..94adc65b 100644 --- a/crates/aiken-lang/src/tipo/environment.rs +++ b/crates/aiken-lang/src/tipo/environment.rs @@ -1794,6 +1794,12 @@ fn unify_unbound_type(tipo: Rc, own_id: u64, location: Span) -> Result<(), Ok(()) } + Type::Pair { fst, snd } => { + unify_unbound_type(fst.clone(), own_id, location)?; + unify_unbound_type(snd.clone(), own_id, location)?; + + Ok(()) + } Type::Var { .. } => unreachable!(), } diff --git a/crates/aiken-lang/src/tipo/pretty.rs b/crates/aiken-lang/src/tipo/pretty.rs index 65745820..13e8454f 100644 --- a/crates/aiken-lang/src/tipo/pretty.rs +++ b/crates/aiken-lang/src/tipo/pretty.rs @@ -86,6 +86,9 @@ impl Printer { Type::Var { tipo: typ, .. } => self.type_var_doc(&typ.borrow()), Type::Tuple { elems, .. } => self.args_to_aiken_doc(elems).surround("(", ")"), + Type::Pair { fst, snd } => self + .args_to_aiken_doc(&[fst.clone(), snd.clone()]) + .surround("Pair<", ">"), } } diff --git a/crates/aiken-project/src/blueprint/definitions.rs b/crates/aiken-project/src/blueprint/definitions.rs index 0a290de4..251798ea 100644 --- a/crates/aiken-project/src/blueprint/definitions.rs +++ b/crates/aiken-project/src/blueprint/definitions.rs @@ -145,6 +145,13 @@ impl Reference { elems = Self::from_types(elems, type_parameters) ), }, + Type::Pair { fst, snd } => Self { + inner: format!( + "Pair{fst}{snd}", + fst = Self::from_type(fst, type_parameters), + snd = Self::from_type(snd, type_parameters) + ), + }, // NOTE: // diff --git a/crates/aiken-project/src/blueprint/schema.rs b/crates/aiken-project/src/blueprint/schema.rs index a649c5fc..206d2891 100644 --- a/crates/aiken-project/src/blueprint/schema.rs +++ b/crates/aiken-project/src/blueprint/schema.rs @@ -384,6 +384,7 @@ impl Annotated { } }, Type::Fn { .. } => unreachable!(), + Type::Pair { .. } => unreachable!(), } } }