Skip to content

Commit

Permalink
Start working on separating pairs from 2 tuples in Aiken
Browse files Browse the repository at this point in the history
co-authored-by: KtorZ <matthias.benkort@gmail.com>
  • Loading branch information
MicroProofs and KtorZ committed May 3, 2024
1 parent a9c8054 commit feb0d4d
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 52 deletions.
4 changes: 4 additions & 0 deletions crates/aiken-lang/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,10 @@ pub fn tuple(elems: Vec<Rc<Type>>) -> Rc<Type> {
Rc::new(Type::Tuple { elems, alias: None })
}

pub fn pair(fst: Rc<Type>, snd: Rc<Type>) -> Rc<Type> {
Rc::new(Type::Pair { fst, snd })
}

pub fn bool() -> Rc<Type> {
Rc::new(Type::App {
args: vec![],
Expand Down
51 changes: 28 additions & 23 deletions crates/aiken-lang/src/gen_uplc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -4310,31 +4310,31 @@ 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()),
))
.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);
Expand All @@ -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()),
Expand All @@ -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));
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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] != "_" {
Expand Down
12 changes: 6 additions & 6 deletions crates/aiken-lang/src/gen_uplc/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -356,7 +356,7 @@ pub fn get_generic_variant_name(t: &Rc<Type>) -> 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()
Expand Down Expand Up @@ -941,7 +941,7 @@ pub fn known_data_to_type(term: Term<Name>, field_type: &Type) -> Term<Name> {
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"))))
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -1313,7 +1313,7 @@ pub fn convert_type_to_data(term: Term<Name>, field_type: &Rc<Type>) -> Term<Nam
Term::map_data().apply(term)
} else if field_type.is_string() {
Term::b_data().apply(Term::Builtin(DefaultFunction::EncodeUtf8).apply(term))
} else if field_type.is_tuple() && matches!(field_type.get_uplc_type(), UplcType::Pair(_, _)) {
} else if field_type.is_pair() {
Term::list_data()
.apply(
Term::mk_cons()
Expand Down
57 changes: 34 additions & 23 deletions crates/aiken-lang/src/tipo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ pub enum Type {
elems: Vec<Rc<Type>>,
alias: Option<Rc<TypeAliasAnnotation>>,
},

Pair {
fst: Rc<Type>,
snd: Rc<Type>,
},
}

impl PartialEq for Type {
Expand Down Expand Up @@ -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(),
}
}

Expand All @@ -218,7 +224,7 @@ impl Type {
} => {
*contains_opaque = opaque;
}
Type::Fn { .. } | Type::Var { .. } | Type::Tuple { .. } => (),
Type::Fn { .. } | Type::Var { .. } | Type::Tuple { .. } | Type::Pair { .. } => (),
}
}

Expand Down Expand Up @@ -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,
}
}
Expand All @@ -375,29 +381,30 @@ 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();
}
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(),
}
}

Expand All @@ -412,7 +419,7 @@ impl Type {

pub fn get_generic(&self) -> Option<u64> {
match self {
Type::Var { tipo, .. } => tipo.borrow().get_generic(),
Self::Var { tipo } => tipo.borrow().get_generic(),
_ => None,
}
}
Expand Down Expand Up @@ -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
Expand All @@ -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() {
Expand Down Expand Up @@ -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()
}
}
}
}

Expand Down Expand Up @@ -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,
}
}
Expand Down
6 changes: 6 additions & 0 deletions crates/aiken-lang/src/tipo/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1794,6 +1794,12 @@ fn unify_unbound_type(tipo: Rc<Type>, 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!(),
}
Expand Down

0 comments on commit feb0d4d

Please sign in to comment.