feat: finish tuple conditions

This commit is contained in:
microproofs 2023-07-05 19:21:22 -04:00 committed by Kasey
parent 05b6b2a97d
commit 95af421f95
2 changed files with 216 additions and 28 deletions

View File

@ -4,7 +4,7 @@ pub mod tree;
use std::sync::Arc; use std::sync::Arc;
use indexmap::IndexMap; use indexmap::{IndexMap, IndexSet};
use itertools::Itertools; use itertools::Itertools;
use uplc::{ use uplc::{
ast::{Name, Program, Term}, ast::{Name, Program, Term},
@ -21,10 +21,11 @@ use crate::{
gen_uplc::{ gen_uplc::{
air::Air, air::Air,
builder::{ builder::{
self as build, lookup_data_type_by_tipo, AssignmentProperties, ClauseProperties, self as build, AssignmentProperties, ClauseProperties, DataTypeKey, FunctionAccessKey,
DataTypeKey, FunctionAccessKey, SpecificClause, SpecificClause,
}, },
}, },
gen_uplc2::builder::convert_opaque_type,
tipo::{ tipo::{
ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor, ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
ValueConstructorVariant, ValueConstructorVariant,
@ -80,9 +81,9 @@ impl<'a> CodeGenerator<'a> {
pub fn generate( pub fn generate(
&mut self, &mut self,
TypedValidator { TypedValidator {
fun, fun: _,
other_fun, other_fun: _,
params, params: _,
.. ..
}: &TypedValidator, }: &TypedValidator,
) -> Program<Name> { ) -> Program<Name> {
@ -99,7 +100,7 @@ impl<'a> CodeGenerator<'a> {
todo!() todo!()
} }
fn finalize(&mut self, term: Term<Name>) -> Program<Name> { fn finalize(&mut self, _term: Term<Name>) -> Program<Name> {
todo!() todo!()
} }
@ -1044,6 +1045,7 @@ impl<'a> CodeGenerator<'a> {
let tuple_inner_types = tipo.get_inner_types(); let tuple_inner_types = tipo.get_inner_types();
let pair_name = format!("__pair_span_{}_{}", location.start, location.end); let pair_name = format!("__pair_span_{}_{}", location.start, location.end);
let fst_name = format!("__pair_fst_span_{}_{}", location.start, location.end); let fst_name = format!("__pair_fst_span_{}_{}", location.start, location.end);
let snd_name = format!("__pair_snd_span_{}_{}", location.start, location.end); let snd_name = format!("__pair_snd_span_{}_{}", location.start, location.end);
@ -1078,13 +1080,61 @@ impl<'a> CodeGenerator<'a> {
]) ])
.hoist_over(AirTree::void()) .hoist_over(AirTree::void())
} else if tipo.is_tuple() { } else if tipo.is_tuple() {
todo!() let tuple_inner_types = tipo.get_inner_types();
let tuple_name = format!("__tuple_span_{}_{}", location.start, location.end);
let tuple_assign = AirTree::let_assignment(&tuple_name, value);
let tuple_expect_items = tuple_inner_types
.iter()
.enumerate()
.map(|(index, arg)| {
let tuple_index_name = format!(
"__tuple_index_{}_span_{}_{}",
index, location.start, location.end
);
let expect_tuple_item = self.expect_type_assign(
tipo,
AirTree::local_var(&tuple_index_name, arg.clone()),
defined_data_types,
location,
);
(tuple_index_name, expect_tuple_item)
})
.collect_vec();
let tuple_index_names = tuple_expect_items
.iter()
.map(|(name, _)| name.clone())
.collect_vec();
let tuple_access = AirTree::tuple_access(
tuple_index_names,
tipo.clone(),
false,
AirTree::local_var(tuple_name, tipo.clone()),
);
let mut tuple_expects = tuple_expect_items
.into_iter()
.map(|(_, item)| item)
.collect_vec();
let mut sequence = vec![tuple_assign, tuple_access];
sequence.append(&mut tuple_expects);
AirTree::UnhoistedSequence(sequence).hoist_over(AirTree::void())
} else { } else {
let data_type = let data_type =
build::lookup_data_type_by_tipo(&self.data_types, tipo).unwrap_or_else(|| { build::lookup_data_type_by_tipo(&self.data_types, tipo).unwrap_or_else(|| {
unreachable!("We need a data type definition fot type {:#?}", tipo) unreachable!("We need a data type definition fot type {:#?}", tipo)
}); });
let mut tipo = convert_opaque_type();
// for (index, arg) in tipo.arg_types().unwrap().iter().enumerate() { // for (index, arg) in tipo.arg_types().unwrap().iter().enumerate() {
// let field_type = arg.clone(); // let field_type = arg.clone();
// type_map.insert(index, field_type); // type_map.insert(index, field_type);
@ -1093,7 +1143,7 @@ impl<'a> CodeGenerator<'a> {
// TODO calculate the variant name. // TODO calculate the variant name.
let data_type_name = format!("__expect_{}{}", data_type.name, ""); let data_type_name = format!("__expect_{}{}", data_type.name, "");
let function = self.code_gen_functions.get(&data_type_name); let function = self.code_gen_functions.get(&data_type_name);
todo!();
if function.is_none() && defined_data_types.get(&data_type_name).is_none() { if function.is_none() && defined_data_types.get(&data_type_name).is_none() {
todo!() todo!()
} else if let Some(counter) = defined_data_types.get_mut(&data_type_name) { } else if let Some(counter) = defined_data_types.get_mut(&data_type_name) {
@ -1104,7 +1154,7 @@ impl<'a> CodeGenerator<'a> {
let func_var = AirTree::var( let func_var = AirTree::var(
ValueConstructor::public( ValueConstructor::public(
tipo.clone(), tipo,
ValueConstructorVariant::ModuleFn { ValueConstructorVariant::ModuleFn {
name: data_type_name.to_string(), name: data_type_name.to_string(),
field_map: None, field_map: None,
@ -1167,14 +1217,11 @@ impl<'a> CodeGenerator<'a> {
let complex_clause = props.complex_clause; let complex_clause = props.complex_clause;
let mut next_clause_props = ClauseProperties { let mut next_clause_props = ClauseProperties::init(
clause_var_name: props.clause_var_name.clone(), subject_tipo,
complex_clause: false, props.clause_var_name.clone(),
needs_constr_var: false, props.original_subject_name.clone(),
original_subject_name: props.original_subject_name.clone(), );
final_clause: false,
specific_clause: props.specific_clause.clone(),
};
if let Some(data_type) = data_type { if let Some(data_type) = data_type {
if data_type.constructors.len() > 1 { if data_type.constructors.len() > 1 {
@ -1340,7 +1387,62 @@ impl<'a> CodeGenerator<'a> {
) )
} }
} }
SpecificClause::TupleClause { .. } => todo!(), SpecificClause::TupleClause {
defined_tuple_indices,
} => {
let current_defined_indices = defined_tuple_indices.clone();
let (_, pattern_assigns) =
self.clause_pattern(&clause.pattern, subject_tipo, props);
let ClauseProperties{ specific_clause: SpecificClause::TupleClause { defined_tuple_indices }, ..} = props
else {
unreachable!()
};
let new_defined_indices: IndexSet<(usize, String)> = defined_tuple_indices
.difference(&current_defined_indices)
.cloned()
.collect();
let mut next_clause_props = ClauseProperties {
clause_var_name: props.clause_var_name.clone(),
complex_clause: false,
needs_constr_var: false,
original_subject_name: props.original_subject_name.clone(),
final_clause: false,
specific_clause: SpecificClause::TupleClause {
defined_tuple_indices: defined_tuple_indices.clone(),
},
};
if new_defined_indices.is_empty() {
AirTree::wrap_clause(
pattern_assigns.hoist_over(clause_then),
self.handle_each_clause(
rest_clauses,
final_clause,
subject_tipo,
&mut next_clause_props,
),
)
} else {
AirTree::tuple_clause(
&props.original_subject_name,
subject_tipo.clone(),
new_defined_indices,
current_defined_indices,
pattern_assigns.hoist_over(clause_then),
self.handle_each_clause(
rest_clauses,
final_clause,
subject_tipo,
&mut next_clause_props,
),
props.complex_clause,
)
}
}
} }
} else { } else {
// handle final_clause // handle final_clause
@ -1607,7 +1709,98 @@ impl<'a> CodeGenerator<'a> {
) )
} }
} }
Pattern::Tuple { .. } => todo!(), Pattern::Tuple { elems, .. } => {
let items_type = subject_tipo.get_inner_types();
let name_index_assigns = elems
.iter()
.enumerate()
.map(|(index, element)| {
let elem_name = match element {
Pattern::Var { name, .. } => name.to_string(),
Pattern::Assign { name, .. } => name.to_string(),
Pattern::Discard { .. } => "_".to_string(),
_ => format!(
"tuple_index_{}_span_{}_{}",
index,
element.location().start,
element.location().end
),
};
let mut tuple_props = ClauseProperties::init_inner(
&items_type[index],
elem_name.clone(),
elem_name.clone(),
props.final_clause,
);
let elem = self.nested_clause_condition(
element,
&items_type[index],
&mut tuple_props,
);
(elem_name, index, elem)
})
.collect_vec();
let mut defined_indices = match props.clone() {
ClauseProperties {
specific_clause:
SpecificClause::TupleClause {
defined_tuple_indices,
},
..
} => defined_tuple_indices,
_ => unreachable!(),
};
let mut previous_defined_names = vec![];
name_index_assigns.iter().for_each(|(name, index, _)| {
if let Some((index, prev_name)) = defined_indices
.iter()
.find(|(defined_index, _)| defined_index == index)
{
previous_defined_names.push((*index, prev_name.clone(), name.clone()));
} else {
assert!(defined_indices.insert((*index, name.clone())));
}
});
let tuple_name_assigns = previous_defined_names
.into_iter()
.map(|(index, prev_name, name)| {
AirTree::let_assignment(
name,
AirTree::local_var(prev_name, items_type[index].clone()),
)
})
.collect_vec();
let mut tuple_item_assigns = name_index_assigns
.into_iter()
.map(|(_, _, item)| item)
.collect_vec();
match props {
ClauseProperties {
specific_clause:
SpecificClause::TupleClause {
defined_tuple_indices,
},
..
} => {
*defined_tuple_indices = defined_indices;
}
_ => unreachable!(),
}
let mut sequence = tuple_name_assigns;
sequence.append(&mut tuple_item_assigns);
(AirTree::void(), AirTree::UnhoistedSequence(sequence))
}
} }
} }
@ -1639,11 +1832,7 @@ impl<'a> CodeGenerator<'a> {
self.nested_clause_condition(pattern, subject_tipo, props), self.nested_clause_condition(pattern, subject_tipo, props),
]), ]),
Pattern::Discard { .. } => AirTree::no_op(), Pattern::Discard { .. } => AirTree::no_op(),
Pattern::List { Pattern::List { .. } => {
location,
elements,
tail,
} => {
todo!(); todo!();
} }
Pattern::Constructor { Pattern::Constructor {
@ -1671,7 +1860,7 @@ impl<'a> CodeGenerator<'a> {
]) ])
} }
} }
Pattern::Tuple { location, elems } => todo!(), Pattern::Tuple { .. } => todo!(),
} }
} }
} }

View File

@ -5,7 +5,6 @@ use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction};
use crate::{ use crate::{
ast::{BinOp, Span, UnOp}, ast::{BinOp, Span, UnOp},
builtins::{data, list, void}, builtins::{data, list, void},
gen_uplc::air,
tipo::{Type, ValueConstructor, ValueConstructorVariant}, tipo::{Type, ValueConstructor, ValueConstructorVariant},
}; };
@ -923,7 +922,7 @@ impl AirTree {
right, right,
} => { } => {
air_vec.push(Air::BinOp { air_vec.push(Air::BinOp {
name: name.clone(), name: *name,
tipo: tipo.clone(), tipo: tipo.clone(),
}); });
left.create_air_vec(air_vec); left.create_air_vec(air_vec);