From 61a021f9e3bd0c6043533bda20c5368ec167e2e5 Mon Sep 17 00:00:00 2001 From: microproofs Date: Wed, 13 Mar 2024 14:08:10 -0400 Subject: [PATCH] update pair to handle alias --- crates/aiken-lang/src/ast.rs | 20 ++++++- crates/aiken-lang/src/builtins.rs | 6 +- crates/aiken-lang/src/format.rs | 1 + crates/aiken-lang/src/tipo.rs | 58 +++++++++++++++---- crates/aiken-lang/src/tipo/environment.rs | 18 +++++- crates/aiken-lang/src/tipo/expr.rs | 4 ++ crates/aiken-lang/src/tipo/hydrator.rs | 8 ++- crates/aiken-lang/src/tipo/infer.rs | 11 +++- crates/aiken-lang/src/tipo/pretty.rs | 2 +- .../src/blueprint/definitions.rs | 2 +- 10 files changed, 111 insertions(+), 19 deletions(-) diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs index 0beff3a2..cb3c9e94 100644 --- a/crates/aiken-lang/src/ast.rs +++ b/crates/aiken-lang/src/ast.rs @@ -970,6 +970,11 @@ pub enum Annotation { location: Span, elems: Vec, }, + Pair { + location: Span, + fst: Box, + snd: Box, + }, } impl Annotation { @@ -979,7 +984,8 @@ impl Annotation { | Annotation::Tuple { location, .. } | Annotation::Var { location, .. } | Annotation::Hole { location, .. } - | Annotation::Constructor { location, .. } => *location, + | Annotation::Constructor { location, .. } + | Annotation::Pair { location, .. } => *location, } } @@ -1081,6 +1087,18 @@ impl Annotation { } => name == o_name, _ => false, }, + Annotation::Pair { fst, snd, .. } => { + if let Annotation::Pair { + fst: o_fst, + snd: o_snd, + .. + } = other + { + fst.is_logically_equal(o_fst) && snd.is_logically_equal(o_snd) + } else { + false + } + } } } diff --git a/crates/aiken-lang/src/builtins.rs b/crates/aiken-lang/src/builtins.rs index 90bda4fc..0e8acbf1 100644 --- a/crates/aiken-lang/src/builtins.rs +++ b/crates/aiken-lang/src/builtins.rs @@ -1335,7 +1335,11 @@ pub fn tuple(elems: Vec>) -> Rc { } pub fn pair(fst: Rc, snd: Rc) -> Rc { - Rc::new(Type::Pair { fst, snd }) + Rc::new(Type::Pair { + fst, + snd, + alias: None, + }) } pub fn bool() -> Rc { diff --git a/crates/aiken-lang/src/format.rs b/crates/aiken-lang/src/format.rs index 3114b435..bb715843 100644 --- a/crates/aiken-lang/src/format.rs +++ b/crates/aiken-lang/src/format.rs @@ -424,6 +424,7 @@ impl<'comments> Formatter<'comments> { Annotation::Tuple { elems, .. } => { wrap_args(elems.iter().map(|t| (self.annotation(t), false))) } + Annotation::Pair { .. } => todo!(), } .group() } diff --git a/crates/aiken-lang/src/tipo.rs b/crates/aiken-lang/src/tipo.rs index 3b64ece4..1286f54d 100644 --- a/crates/aiken-lang/src/tipo.rs +++ b/crates/aiken-lang/src/tipo.rs @@ -75,6 +75,7 @@ pub enum Type { Pair { fst: Rc, snd: Rc, + alias: Option>, }, } @@ -143,6 +144,18 @@ impl PartialEq for Type { false } } + Type::Pair { fst, snd, .. } => { + if let Type::Pair { + fst: fst2, + snd: snd2, + .. + } = other + { + fst == fst2 && snd == snd2 + } else { + false + } + } } } } @@ -153,7 +166,8 @@ impl Type { Type::App { alias, .. } | Type::Fn { alias, .. } | Type::Var { alias, .. } - | Type::Tuple { alias, .. } => alias.clone(), + | Type::Tuple { alias, .. } + | Type::Pair { alias, .. } => alias.clone(), } } @@ -188,6 +202,7 @@ impl Type { } => Type::Fn { args, ret, alias }, Type::Var { tipo, alias: _ } => Type::Var { tipo, alias }, Type::Tuple { elems, alias: _ } => Type::Tuple { elems, alias }, + Type::Pair { fst, snd, alias: _ } => Type::Pair { fst, snd, alias }, }) } @@ -200,6 +215,7 @@ impl Type { _ => None, }, Type::Tuple { .. } => Some((String::new(), "Tuple".to_string())), + Type::Pair { .. } => Some((String::new(), "Pair".to_string())), } } @@ -350,14 +366,14 @@ impl Type { .first() .expect("unreachable: List should have an inner type") .is_pair(), - Self::Var { tipo } => tipo.borrow().is_map(), + Self::Var { tipo, .. } => tipo.borrow().is_map(), _ => false, } } pub fn is_tuple(&self) -> bool { match self { - Self::Var { tipo } => tipo.borrow().is_tuple(), + Self::Var { tipo, .. } => tipo.borrow().is_tuple(), Self::Tuple { .. } => true, _ => false, } @@ -365,7 +381,7 @@ impl Type { pub fn is_pair(&self) -> bool { match self { - Self::Var { tipo } => tipo.borrow().is_pair(), + Self::Var { tipo, .. } => tipo.borrow().is_pair(), Self::Pair { .. } => true, _ => false, } @@ -389,22 +405,22 @@ impl Type { is_a_generic } - Self::Var { tipo } => tipo.borrow().is_generic(), - Self::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 } - Self::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(), + Self::Pair { fst, snd, .. } => fst.is_generic() || snd.is_generic(), } } @@ -419,7 +435,7 @@ impl Type { pub fn get_generic(&self) -> Option { match self { - Self::Var { tipo } => tipo.borrow().get_generic(), + Self::Var { tipo, .. } => tipo.borrow().get_generic(), _ => None, } } @@ -470,7 +486,7 @@ impl Type { } else if self.is_tuple() { match self { Self::Tuple { .. } => UplcType::List(UplcType::Data.into()), - Self::Var { tipo } => tipo.borrow().get_uplc_type().unwrap(), + Self::Var { tipo, .. } => tipo.borrow().get_uplc_type().unwrap(), _ => unreachable!(), } } else if self.is_pair() { @@ -563,7 +579,7 @@ impl Type { TypeVar::Link { tipo, .. } => tipo.find_private_type(), }, - Self::Pair { fst, snd } => { + Self::Pair { fst, snd, .. } => { if let Some(private_type) = fst.find_private_type() { Some(private_type) } else { @@ -749,6 +765,16 @@ pub fn convert_opaque_type( } .into() } + Type::Pair { fst, snd, alias } => { + let fst = convert_opaque_type(fst, data_types, deep); + let snd = convert_opaque_type(snd, data_types, deep); + Type::Pair { + fst, + snd, + alias: alias.clone(), + } + .into() + } } } } @@ -838,6 +864,16 @@ pub fn find_and_replace_generics( TypeVar::Generic { .. } | TypeVar::Unbound { .. } => unreachable!(), } } + Type::Pair { fst, snd, alias } => { + let fst = find_and_replace_generics(fst, mono_types); + let snd = find_and_replace_generics(snd, mono_types); + Type::Pair { + fst, + snd, + alias: alias.clone(), + } + .into() + } } } else { tipo.clone() diff --git a/crates/aiken-lang/src/tipo/environment.rs b/crates/aiken-lang/src/tipo/environment.rs index 94adc65b..e74a82e2 100644 --- a/crates/aiken-lang/src/tipo/environment.rs +++ b/crates/aiken-lang/src/tipo/environment.rs @@ -11,7 +11,7 @@ use crate::{ RecordConstructor, RecordConstructorArg, Span, TypeAlias, TypedDefinition, TypedPattern, UnqualifiedImport, UntypedArg, UntypedDefinition, Use, Validator, PIPE_VARIABLE, }, - builtins::{function, generic_var, tuple, unbound_var}, + builtins::{function, generic_var, pair, tuple, unbound_var}, tipo::{fields::FieldMap, TypeAliasAnnotation}, IdGenerator, }; @@ -644,6 +644,13 @@ impl<'a> Environment<'a> { ), alias.clone(), ), + Type::Pair { fst, snd, alias } => Type::with_alias( + pair( + self.instantiate(fst.clone(), ids, hydrator), + self.instantiate(snd.clone(), ids, hydrator), + ), + alias.clone(), + ), } } @@ -1794,7 +1801,7 @@ fn unify_unbound_type(tipo: Rc, own_id: u64, location: Span) -> Result<(), Ok(()) } - Type::Pair { fst, snd } => { + Type::Pair { fst, snd, .. } => { unify_unbound_type(fst.clone(), own_id, location)?; unify_unbound_type(snd.clone(), own_id, location)?; @@ -1976,5 +1983,12 @@ pub(crate) fn generalise(t: Rc, ctx_level: usize) -> Rc { ), alias.clone(), ), + Type::Pair { fst, snd, alias } => Type::with_alias( + pair( + generalise(fst.clone(), ctx_level), + generalise(snd.clone(), ctx_level), + ), + alias.clone(), + ), } } diff --git a/crates/aiken-lang/src/tipo/expr.rs b/crates/aiken-lang/src/tipo/expr.rs index 7aa932f9..6f3c7310 100644 --- a/crates/aiken-lang/src/tipo/expr.rs +++ b/crates/aiken-lang/src/tipo/expr.rs @@ -2442,5 +2442,9 @@ pub fn ensure_serialisable(allow_fn: bool, t: Rc, location: Span) -> Resul location, ), }, + Type::Pair { fst, snd, .. } => { + ensure_serialisable(false, fst.clone(), location)?; + ensure_serialisable(false, snd.clone(), location) + } } } diff --git a/crates/aiken-lang/src/tipo/hydrator.rs b/crates/aiken-lang/src/tipo/hydrator.rs index f4d3ec04..9b66a301 100644 --- a/crates/aiken-lang/src/tipo/hydrator.rs +++ b/crates/aiken-lang/src/tipo/hydrator.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{ ast::Annotation, - builtins::{function, tuple}, + builtins::{function, pair, tuple}, tipo::Span, }; use std::{collections::HashMap, rc::Rc}; @@ -246,6 +246,12 @@ impl Hydrator { Ok(tuple(typed_elems)) } + Annotation::Pair { fst, snd, .. } => { + let fst = self.do_type_from_annotation(fst, environment, unbounds)?; + let snd = self.do_type_from_annotation(snd, environment, unbounds)?; + + Ok(pair(fst, snd)) + } }?; Ok(environment.annotate(return_type, annotation)) diff --git a/crates/aiken-lang/src/tipo/infer.rs b/crates/aiken-lang/src/tipo/infer.rs index 7b3e9b0c..f4f6cd85 100644 --- a/crates/aiken-lang/src/tipo/infer.rs +++ b/crates/aiken-lang/src/tipo/infer.rs @@ -843,7 +843,7 @@ fn infer_fuzzer( }), }, - Type::App { .. } | Type::Tuple { .. } => Err(could_not_unify()), + Type::App { .. } | Type::Tuple { .. } | Type::Pair { .. } => Err(could_not_unify()), } } @@ -894,5 +894,14 @@ fn annotate_fuzzer(tipo: &Type, location: &Span) -> Result { location: *location, tipo: Rc::new(tipo.clone()), }), + Type::Pair { fst, snd, .. } => { + let fst = annotate_fuzzer(fst, location)?; + let snd = annotate_fuzzer(snd, location)?; + Ok(Annotation::Pair { + fst: Box::new(fst), + snd: Box::new(snd), + location: *location, + }) + } } } diff --git a/crates/aiken-lang/src/tipo/pretty.rs b/crates/aiken-lang/src/tipo/pretty.rs index 13e8454f..4b614a09 100644 --- a/crates/aiken-lang/src/tipo/pretty.rs +++ b/crates/aiken-lang/src/tipo/pretty.rs @@ -86,7 +86,7 @@ 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 + 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 251798ea..f71457be 100644 --- a/crates/aiken-project/src/blueprint/definitions.rs +++ b/crates/aiken-project/src/blueprint/definitions.rs @@ -145,7 +145,7 @@ impl Reference { elems = Self::from_types(elems, type_parameters) ), }, - Type::Pair { fst, snd } => Self { + Type::Pair { fst, snd, .. } => Self { inner: format!( "Pair{fst}{snd}", fst = Self::from_type(fst, type_parameters),