chore: another checkpoint and renamed ClauseProperties fields

This commit is contained in:
microproofs 2023-06-30 01:56:23 -04:00 committed by Kasey
parent d731757123
commit 0854d71836
5 changed files with 377 additions and 492 deletions

View File

@ -39,7 +39,11 @@ use builder::{
AssignmentProperties, ClauseProperties, DataTypeKey, FuncComponents, FunctionAccessKey,
};
use self::{builder::replace_opaque_type, scope::Scope, stack::AirStack};
use self::{
builder::{replace_opaque_type, SpecificClause},
scope::Scope,
stack::AirStack,
};
#[derive(Clone, Debug)]
pub enum CodeGenFunction {
@ -571,7 +575,7 @@ impl<'a> CodeGenerator<'a> {
self.build(&last_clause.then, &mut final_clause_stack);
*clause_properties.is_final_clause() = true;
clause_properties.final_clause = true;
self.when_pattern(
last_pattern,
@ -587,7 +591,7 @@ impl<'a> CodeGenerator<'a> {
finally_stack.merge(final_pattern_stack);
}
if *clause_properties.needs_constr_var() {
if clause_properties.needs_constr_var {
let mut subject_stack = ir_stack.empty_with_scope();
self.build(subject, &mut subject_stack);
@ -813,7 +817,7 @@ impl<'a> CodeGenerator<'a> {
let mut clause_then_stack = ir_stack.empty_with_scope();
// reset complex clause setting per clause back to default
*clause_properties.is_complex_clause() = false;
clause_properties.complex_clause = false;
self.build(&clause.then, &mut clause_then_stack);
@ -821,7 +825,7 @@ impl<'a> CodeGenerator<'a> {
let mut clause_guard_stack = ir_stack.empty_with_scope();
let mut clause_guard_condition = ir_stack.empty_with_scope();
*clause_properties.is_complex_clause() = true;
clause_properties.complex_clause = true;
let clause_guard_name = format!("__clause_guard_{}", self.id_gen.next());
@ -856,8 +860,9 @@ impl<'a> CodeGenerator<'a> {
);
match clause_properties {
ClauseProperties::ConstrClause {
ClauseProperties {
original_subject_name,
specific_clause: SpecificClause::ConstrClause,
..
} => {
let subject_name = original_subject_name.clone();
@ -873,7 +878,7 @@ impl<'a> CodeGenerator<'a> {
ir_stack.clause(
subject_type.clone(),
subject_name,
*clause_properties.is_complex_clause(),
clause_properties.complex_clause,
clause_pattern_stack,
);
} else {
@ -886,7 +891,7 @@ impl<'a> CodeGenerator<'a> {
ir_stack.clause(
subject_type.clone(),
subject_name,
*clause_properties.is_complex_clause(),
clause_properties.complex_clause,
condition_stack,
);
}
@ -894,15 +899,15 @@ impl<'a> CodeGenerator<'a> {
ir_stack.clause(
subject_type.clone(),
subject_name,
*clause_properties.is_complex_clause(),
clause_properties.complex_clause,
clause_pattern_stack,
);
}
}
}
ClauseProperties::ListClause {
ClauseProperties {
original_subject_name,
current_index,
specific_clause: SpecificClause::ListClause { current_index, .. },
..
} => {
let original_subject_name = original_subject_name.clone();
@ -958,7 +963,7 @@ impl<'a> CodeGenerator<'a> {
subject_type.clone(),
subject_name,
next_tail,
*clause_properties.is_complex_clause(),
clause_properties.complex_clause,
clause_pattern_stack,
);
}
@ -966,12 +971,15 @@ impl<'a> CodeGenerator<'a> {
ir_stack.wrap_clause(clause_pattern_stack);
}
}
ClauseProperties::TupleClause {
ClauseProperties {
original_subject_name,
specific_clause:
SpecificClause::TupleClause {
defined_tuple_indices,
},
..
} => {
let ClauseProperties::TupleClause { defined_tuple_indices: prev_defined_tuple_indices, .. } = prev_clause_properties
let ClauseProperties { specific_clause: SpecificClause::TupleClause { defined_tuple_indices: prev_defined_tuple_indices}, ..} = prev_clause_properties
else {
unreachable!()
};
@ -988,8 +996,7 @@ impl<'a> CodeGenerator<'a> {
subject_name,
indices_to_define,
prev_defined_tuple_indices,
*clause_properties.is_complex_clause()
|| (!*clause_properties.is_final_clause()),
clause_properties.complex_clause || (!clause_properties.final_clause),
clause_pattern_stack,
);
}
@ -1019,19 +1026,16 @@ impl<'a> CodeGenerator<'a> {
var_stack.local_var(
tipo.clone().into(),
match clause_properties {
ClauseProperties::ConstrClause {
ClauseProperties {
clause_var_name,
needs_constr_var,
specific_clause: SpecificClause::ConstrClause,
..
} => {
*needs_constr_var = true;
clause_var_name
}
ClauseProperties::ListClause {
original_subject_name,
..
} => original_subject_name,
ClauseProperties::TupleClause {
ClauseProperties {
original_subject_name,
..
} => original_subject_name,
@ -1048,19 +1052,16 @@ impl<'a> CodeGenerator<'a> {
new_stack.local_var(
tipo.clone().into(),
match clause_properties {
ClauseProperties::ConstrClause {
ClauseProperties {
clause_var_name,
needs_constr_var,
specific_clause: SpecificClause::ConstrClause,
..
} => {
*needs_constr_var = true;
clause_var_name
}
ClauseProperties::ListClause {
original_subject_name,
..
} => original_subject_name,
ClauseProperties::TupleClause {
ClauseProperties {
original_subject_name,
..
} => original_subject_name,
@ -1088,7 +1089,7 @@ impl<'a> CodeGenerator<'a> {
builder::check_when_pattern_needs(tail, clause_properties);
}
*clause_properties.needs_constr_var() = false;
clause_properties.needs_constr_var = false;
let mut void_stack = pattern_stack.empty_with_scope();
@ -1104,7 +1105,7 @@ impl<'a> CodeGenerator<'a> {
..
} => {
let mut temp_clause_properties = clause_properties.clone();
*temp_clause_properties.needs_constr_var() = false;
temp_clause_properties.needs_constr_var = false;
if tipo.is_bool() {
pattern_stack.bool(constr_name == "True");
@ -1126,20 +1127,18 @@ impl<'a> CodeGenerator<'a> {
let mut new_stack = pattern_stack.empty_with_scope();
new_stack.local_var(
tipo.clone().into(),
temp_clause_properties.clause_var_name(),
);
new_stack
.local_var(tipo.clone().into(), temp_clause_properties.clause_var_name);
// if only one constructor, no need to check
if data_type.constructors.len() > 1 || *clause_properties.is_final_clause() {
if data_type.constructors.len() > 1 || clause_properties.final_clause {
// push constructor Index
let mut tag_stack = pattern_stack.empty_with_scope();
tag_stack.integer(index.to_string());
pattern_stack.merge_child(tag_stack);
}
if *temp_clause_properties.needs_constr_var() {
if temp_clause_properties.needs_constr_var {
self.expose_elements(
pattern,
pattern_stack,
@ -1163,18 +1162,18 @@ impl<'a> CodeGenerator<'a> {
pattern_stack.merge_child(value_stack);
// unify clause properties
*clause_properties.is_complex_clause() = *clause_properties.is_complex_clause()
|| *temp_clause_properties.is_complex_clause();
clause_properties.complex_clause =
clause_properties.complex_clause || temp_clause_properties.complex_clause;
*clause_properties.needs_constr_var() = *clause_properties.needs_constr_var()
|| *temp_clause_properties.needs_constr_var();
clause_properties.needs_constr_var =
clause_properties.needs_constr_var || temp_clause_properties.needs_constr_var;
}
Pattern::Tuple { elems, .. } => {
for elem in elems {
builder::check_when_pattern_needs(elem, clause_properties);
}
*clause_properties.needs_constr_var() = false;
clause_properties.needs_constr_var = false;
let temp = pattern_stack.empty_with_scope();
@ -1185,8 +1184,8 @@ impl<'a> CodeGenerator<'a> {
}
// final clause can not be complex
if *(clause_properties.is_final_clause()) {
*clause_properties.is_complex_clause() = false;
if clause_properties.final_clause {
clause_properties.complex_clause = false;
}
}
@ -1217,7 +1216,7 @@ impl<'a> CodeGenerator<'a> {
element,
&mut nested_pattern,
items_type,
*clause_properties.is_final_clause(),
clause_properties.final_clause,
);
names.push(name.unwrap_or_else(|| "_".to_string()))
@ -1244,7 +1243,7 @@ impl<'a> CodeGenerator<'a> {
.map(|(index, name)| {
if index == 0 {
(
clause_properties.original_subject_name().clone(),
clause_properties.original_subject_name.clone(),
name.clone(),
)
} else {
@ -1254,7 +1253,7 @@ impl<'a> CodeGenerator<'a> {
.collect_vec();
let tail_var = if elements.len() == 1 || elements.is_empty() {
clause_properties.original_subject_name().clone()
clause_properties.original_subject_name.clone()
} else {
format!("__tail_{}", elements.len() - 2)
};
@ -1331,7 +1330,7 @@ impl<'a> CodeGenerator<'a> {
}
.into(),
),
*clause_properties.is_final_clause(),
clause_properties.final_clause,
);
var_name.map_or(
@ -1374,7 +1373,7 @@ impl<'a> CodeGenerator<'a> {
&item.value,
&mut nested_pattern,
type_map.get(&index).unwrap(),
*clause_properties.is_final_clause(),
clause_properties.final_clause,
);
var_name.map_or(("_".to_string(), index), |var_name| (var_name, index))
@ -1411,7 +1410,7 @@ impl<'a> CodeGenerator<'a> {
element,
&mut nested_pattern,
&items_type[index],
*clause_properties.is_final_clause(),
clause_properties.final_clause,
);
name.map(|name| (name, index))
@ -1419,8 +1418,11 @@ impl<'a> CodeGenerator<'a> {
.collect_vec();
let mut defined_indices = match clause_properties.clone() {
ClauseProperties::TupleClause {
ClauseProperties {
specific_clause:
SpecificClause::TupleClause {
defined_tuple_indices,
},
..
} => defined_tuple_indices,
_ => unreachable!(),
@ -1455,8 +1457,11 @@ impl<'a> CodeGenerator<'a> {
}
match clause_properties {
ClauseProperties::TupleClause {
ClauseProperties {
specific_clause:
SpecificClause::TupleClause {
defined_tuple_indices,
},
..
} => {
*defined_tuple_indices = defined_indices;
@ -1509,12 +1514,15 @@ impl<'a> CodeGenerator<'a> {
format!("{}_{}", new_tail_name, index - 1)
};
let mut clause_properties = ClauseProperties::ListClause {
let mut clause_properties = ClauseProperties {
clause_var_name: item_name.clone(),
needs_constr_var: false,
is_complex_clause: false,
complex_clause: false,
original_subject_name: item_name.clone(),
specific_clause: SpecificClause::ListClause {
current_index: index as i64,
defined_tails: vec![],
},
final_clause,
};
@ -1606,12 +1614,13 @@ impl<'a> CodeGenerator<'a> {
let mut when_stack = pattern_stack.empty_with_scope();
let mut clause_properties = ClauseProperties::ConstrClause {
let mut clause_properties = ClauseProperties {
clause_var_name: constr_var_name.clone(),
needs_constr_var: false,
is_complex_clause: false,
complex_clause: false,
original_subject_name: constr_var_name.clone(),
final_clause,
specific_clause: SpecificClause::ConstrClause,
};
self.when_pattern(
@ -1652,12 +1661,14 @@ impl<'a> CodeGenerator<'a> {
a @ Pattern::Tuple { .. } => {
let item_name = format!("__tuple_item_id_{}", self.id_gen.next());
let mut clause_properties = ClauseProperties::TupleClause {
let mut clause_properties = ClauseProperties {
clause_var_name: item_name.clone(),
needs_constr_var: false,
is_complex_clause: false,
complex_clause: false,
original_subject_name: item_name.clone(),
specific_clause: SpecificClause::TupleClause {
defined_tuple_indices: IndexSet::new(),
},
final_clause,
};
@ -1672,16 +1683,20 @@ impl<'a> CodeGenerator<'a> {
);
let defined_indices = match clause_properties.clone() {
ClauseProperties::TupleClause {
ClauseProperties {
specific_clause:
SpecificClause::TupleClause {
defined_tuple_indices,
..
},
..
} => defined_tuple_indices,
_ => unreachable!(),
};
pattern_stack.tuple_clause(
pattern_type.clone().into(),
clause_properties.original_subject_name(),
clause_properties.original_subject_name,
defined_indices,
IndexSet::new(),
false,

View File

@ -65,128 +65,60 @@ pub struct AssignmentProperties {
}
#[derive(Clone, Debug)]
pub enum ClauseProperties {
ConstrClause {
clause_var_name: String,
needs_constr_var: bool,
is_complex_clause: bool,
original_subject_name: String,
final_clause: bool,
},
pub struct ClauseProperties {
pub clause_var_name: String,
pub complex_clause: bool,
pub needs_constr_var: bool,
pub original_subject_name: String,
pub final_clause: bool,
pub specific_clause: SpecificClause,
}
#[derive(Clone, Debug)]
pub enum SpecificClause {
ConstrClause,
ListClause {
clause_var_name: String,
needs_constr_var: bool,
is_complex_clause: bool,
original_subject_name: String,
current_index: i64,
final_clause: bool,
defined_tails: Vec<String>,
},
TupleClause {
clause_var_name: String,
needs_constr_var: bool,
is_complex_clause: bool,
original_subject_name: String,
defined_tuple_indices: IndexSet<(usize, String)>,
final_clause: bool,
},
}
impl ClauseProperties {
pub fn init(t: &Arc<Type>, constr_var: String, subject_name: String) -> Self {
if t.is_list() {
ClauseProperties::ListClause {
ClauseProperties {
clause_var_name: constr_var,
needs_constr_var: false,
is_complex_clause: false,
complex_clause: false,
original_subject_name: subject_name,
current_index: -1,
final_clause: false,
needs_constr_var: false,
specific_clause: SpecificClause::ConstrClause,
}
} else if t.is_tuple() {
ClauseProperties::TupleClause {
ClauseProperties {
clause_var_name: constr_var,
needs_constr_var: false,
is_complex_clause: false,
complex_clause: false,
original_subject_name: subject_name,
defined_tuple_indices: IndexSet::new(),
needs_constr_var: false,
final_clause: false,
specific_clause: SpecificClause::TupleClause {
defined_tuple_indices: IndexSet::new(),
},
}
} else {
ClauseProperties::ConstrClause {
ClauseProperties {
clause_var_name: constr_var,
needs_constr_var: false,
is_complex_clause: false,
complex_clause: false,
original_subject_name: subject_name,
needs_constr_var: false,
final_clause: false,
specific_clause: SpecificClause::ConstrClause,
}
}
}
pub fn is_complex_clause(&mut self) -> &mut bool {
match self {
ClauseProperties::ConstrClause {
is_complex_clause, ..
}
| ClauseProperties::ListClause {
is_complex_clause, ..
}
| ClauseProperties::TupleClause {
is_complex_clause, ..
} => is_complex_clause,
}
}
pub fn needs_constr_var(&mut self) -> &mut bool {
match self {
ClauseProperties::ConstrClause {
needs_constr_var, ..
}
| ClauseProperties::ListClause {
needs_constr_var, ..
}
| ClauseProperties::TupleClause {
needs_constr_var, ..
} => needs_constr_var,
}
}
pub fn is_final_clause(&mut self) -> &mut bool {
match self {
ClauseProperties::ConstrClause { final_clause, .. }
| ClauseProperties::ListClause { final_clause, .. }
| ClauseProperties::TupleClause { final_clause, .. } => final_clause,
}
}
pub fn clause_var_name(&mut self) -> &mut String {
match self {
ClauseProperties::ConstrClause {
clause_var_name, ..
}
| ClauseProperties::ListClause {
clause_var_name, ..
}
| ClauseProperties::TupleClause {
clause_var_name, ..
} => clause_var_name,
}
}
pub fn original_subject_name(&mut self) -> &mut String {
match self {
ClauseProperties::ConstrClause {
original_subject_name,
..
}
| ClauseProperties::ListClause {
original_subject_name,
..
}
| ClauseProperties::TupleClause {
original_subject_name,
..
} => original_subject_name,
}
}
}
pub fn convert_type_to_data(term: Term<Name>, field_type: &Arc<Type>) -> Term<Name> {
@ -706,12 +638,12 @@ pub fn check_when_pattern_needs(
) {
match pattern {
Pattern::Var { .. } => {
*clause_properties.needs_constr_var() = true;
clause_properties.needs_constr_var = true;
}
Pattern::List { elements, tail, .. } => {
*clause_properties.needs_constr_var() = true;
clause_properties.needs_constr_var = true;
*clause_properties.is_complex_clause() = true;
clause_properties.complex_clause = true;
for element in elements {
check_when_pattern_needs(element, clause_properties);
@ -721,33 +653,33 @@ pub fn check_when_pattern_needs(
}
}
Pattern::Tuple { elems, .. } => {
*clause_properties.needs_constr_var() = true;
clause_properties.needs_constr_var = true;
*clause_properties.is_complex_clause() = true;
clause_properties.complex_clause = true;
for element in elems {
check_when_pattern_needs(element, clause_properties);
}
}
Pattern::Int { .. } => {
*clause_properties.needs_constr_var() = true;
clause_properties.needs_constr_var = true;
*clause_properties.is_complex_clause() = true;
clause_properties.complex_clause = true;
}
Pattern::Constructor { arguments, .. } => {
*clause_properties.needs_constr_var() = true;
clause_properties.needs_constr_var = true;
*clause_properties.is_complex_clause() = true;
clause_properties.complex_clause = true;
for argument in arguments {
check_when_pattern_needs(&argument.value, clause_properties);
}
}
Pattern::Discard { .. } => {
*clause_properties.needs_constr_var() = true;
clause_properties.needs_constr_var = true;
}
Pattern::Assign { pattern, .. } => {
*clause_properties.needs_constr_var() = true;
clause_properties.needs_constr_var = true;
check_when_pattern_needs(pattern, clause_properties)
}

View File

@ -22,6 +22,7 @@ use crate::{
air::Air,
builder::{
self as build, AssignmentProperties, ClauseProperties, DataTypeKey, FunctionAccessKey,
SpecificClause,
},
},
tipo::{
@ -270,7 +271,7 @@ impl<'a> CodeGenerator<'a> {
value_type: value.tipo(),
kind: *kind,
remove_unused: kind.is_let(),
full_check: false,
full_check: !tipo.is_data() && value.tipo().is_data() && kind.is_expect(),
},
)
}
@ -516,7 +517,7 @@ impl<'a> CodeGenerator<'a> {
}
}
Pattern::Var { name, .. } => {
if props.kind.is_expect() && props.value_type.is_data() && !tipo.is_data() {
if props.full_check {
let mut index_map = IndexMap::new();
// let tipo = builder::convert_opaque_type();
let assignment = AirTree::let_assignment(name, value);
@ -525,12 +526,8 @@ impl<'a> CodeGenerator<'a> {
if tipo.is_primitive() {
AirTree::let_assignment(name, AirTree::hoist_over(assignment, val))
} else {
let expect = self.expect_type(
&tipo,
val.clone(),
&mut index_map,
pattern.location(),
);
let expect =
self.expect_type(tipo, val.clone(), &mut index_map, pattern.location());
let assign =
AirTree::let_assignment("_", AirTree::hoist_over(assignment, expect));
AirTree::let_assignment(name, AirTree::hoist_over(assign, val))
@ -547,7 +544,8 @@ impl<'a> CodeGenerator<'a> {
AirTree::UnhoistedSequence(vec![assign, inner_pattern])
}
Pattern::Discard { name, .. } => {
if props.kind.is_expect() && props.value_type.is_data() && !tipo.is_data() {
if props.full_check {
let name = &format!("__discard_expect_{}", name);
let mut index_map = IndexMap::new();
// let tipo = builder::convert_opaque_type();
let assignment = AirTree::let_assignment(name, value);
@ -584,10 +582,7 @@ impl<'a> CodeGenerator<'a> {
Pattern::Var { name, .. } => name.to_string(),
Pattern::Assign { name, .. } => name.to_string(),
Pattern::Discard { name, .. } => {
if props.kind.is_expect()
&& props.value_type.is_data()
&& !tipo.is_data()
{
if props.full_check {
format!("__discard_{}", name)
} else {
"_".to_string()
@ -613,7 +608,7 @@ impl<'a> CodeGenerator<'a> {
value_type: list_elem_type.clone(),
kind: props.kind,
remove_unused: true,
full_check: false,
full_check: props.full_check,
},
),
)
@ -651,10 +646,10 @@ impl<'a> CodeGenerator<'a> {
val,
tipo,
AssignmentProperties {
value_type: props.value_type.clone(),
value_type: tipo.clone(),
kind: props.kind,
remove_unused: true,
full_check: false,
full_check: props.full_check,
},
),
));
@ -694,9 +689,7 @@ impl<'a> CodeGenerator<'a> {
let data_type = build::lookup_data_type_by_tipo(&self.data_types, tipo)
.unwrap_or_else(|| panic!("Failed to find definition for {}", name));
if data_type.constructors.len() > 1
|| (!tipo.is_data() && props.value_type.is_data())
{
if data_type.constructors.len() > 1 || props.full_check {
let (index, _) = data_type
.constructors
.iter()
@ -759,10 +752,7 @@ impl<'a> CodeGenerator<'a> {
Pattern::Var { name, .. } => name.to_string(),
Pattern::Assign { name, .. } => name.to_string(),
Pattern::Discard { name, .. } => {
if props.kind.is_expect()
&& props.value_type.is_data()
&& !tipo.is_data()
{
if props.full_check {
format!("__discard_{}", name)
} else {
"_".to_string()
@ -797,7 +787,7 @@ impl<'a> CodeGenerator<'a> {
value_type: props.value_type.clone(),
kind: props.kind,
remove_unused: true,
full_check: false,
full_check: props.full_check,
},
),
)
@ -843,10 +833,7 @@ impl<'a> CodeGenerator<'a> {
Pattern::Var { name, .. } => name.to_string(),
Pattern::Assign { name, .. } => name.to_string(),
Pattern::Discard { name, .. } => {
if props.kind.is_expect()
&& props.value_type.is_data()
&& !tipo.is_data()
{
if props.full_check {
format!("__discard_{}", name)
} else {
"_".to_string()
@ -879,7 +866,7 @@ impl<'a> CodeGenerator<'a> {
value_type: props.value_type.clone(),
kind: props.kind,
remove_unused: true,
full_check: false,
full_check: props.full_check,
},
),
)
@ -1034,13 +1021,13 @@ impl<'a> CodeGenerator<'a> {
props: &mut ClauseProperties,
) -> AirTree {
assert!(!clauses.is_empty());
*props.is_complex_clause() = false;
props.complex_clause = false;
if let Some((clause, rest_clauses)) = clauses.split_first() {
todo!()
} else {
// handle final_clause
*props.is_final_clause() = true;
props.final_clause = true;
assert!(final_clause.guard.is_none());
let clause_then = self.build(&final_clause.then);
let (_, assignments) = self.clause_pattern(&final_clause.pattern, subject_tipo, props);
@ -1058,14 +1045,14 @@ impl<'a> CodeGenerator<'a> {
) -> (AirTree, AirTree) {
match pattern {
Pattern::Int { value, .. } => {
assert!(!*props.is_final_clause());
assert!(!props.final_clause);
(AirTree::int(value), AirTree::no_op())
}
Pattern::Var { name, .. } => (
AirTree::void(),
AirTree::let_assignment(
name,
AirTree::local_var(props.clause_var_name(), subject_tipo.clone()),
AirTree::local_var(&props.clause_var_name, subject_tipo.clone()),
),
),
Pattern::Assign { name, pattern, .. } => {
@ -1075,7 +1062,7 @@ impl<'a> CodeGenerator<'a> {
let sequence = vec![
AirTree::let_assignment(
name,
AirTree::local_var(props.clause_var_name(), subject_tipo.clone()),
AirTree::local_var(&props.clause_var_name, subject_tipo.clone()),
),
inner_assignment,
];
@ -1083,7 +1070,119 @@ impl<'a> CodeGenerator<'a> {
(inner_condition, AirTree::UnhoistedSequence(sequence))
}
Pattern::Discard { .. } => (AirTree::void(), AirTree::no_op()),
Pattern::List { .. } => todo!(),
Pattern::List { elements, tail, .. } => {
let ClauseProperties {
specific_clause:
SpecificClause::ListClause {
current_index: _,
defined_tails,
},
clause_var_name: _,
complex_clause: _,
needs_constr_var: _,
original_subject_name: _,
final_clause: _,
} = props
else { unreachable!()};
let list_elem_types = subject_tipo.get_inner_types();
let list_elem_type = list_elem_types
.get(0)
.unwrap_or_else(|| unreachable!("No list element type?"));
let elems = elements
.iter()
.enumerate()
.zip(defined_tails.clone())
.map(|((index, elem), tail)| {
let elem_name = match elem {
Pattern::Var { name, .. } => name.to_string(),
Pattern::Assign { name, .. } => name.to_string(),
Pattern::Discard { .. } => "_".to_string(),
_ => format!(
"elem_{}_span_{}_{}",
index,
elem.location().start,
elem.location().end
),
};
let mut elem_props = ClauseProperties::init(
list_elem_type,
elem_name.clone(),
elem_name.clone(),
);
let statement =
self.nested_clause_condition(elem, list_elem_type, &mut elem_props);
props.complex_clause = props.complex_clause || elem_props.complex_clause;
(tail, elem_name, statement)
})
.collect_vec();
let defined_tail_heads = elems
.iter()
.map(|(tail, head, _)| (tail.to_string(), head.to_string()))
.collect_vec();
let mut air_elems = elems
.into_iter()
.map(|(_, _, statement)| statement)
.collect_vec();
let mut list_tail = None;
tail.iter()
.zip(
defined_tails
.clone()
.get(defined_tails.clone().len() - 1)
.iter(),
)
.for_each(|(elem, tail)| {
let elem_name = match elem.as_ref() {
Pattern::Var { name, .. } => name.to_string(),
Pattern::Assign { name, .. } => name.to_string(),
Pattern::Discard { .. } => "_".to_string(),
_ => format!(
"tail_span_{}_{}",
elem.location().start,
elem.location().end
),
};
let mut elem_props = ClauseProperties {
clause_var_name: elem_name.clone(),
complex_clause: false,
needs_constr_var: false,
original_subject_name: elem_name.clone(),
final_clause: props.final_clause,
specific_clause: props.specific_clause.clone(),
};
let statement =
self.nested_clause_condition(elem, subject_tipo, &mut elem_props);
props.complex_clause = props.complex_clause || elem_props.complex_clause;
air_elems.push(statement);
list_tail = Some((tail.to_string(), elem_name));
});
let list_assign = AirTree::list_expose(
defined_tail_heads,
list_tail,
subject_tipo.clone(),
AirTree::local_var(&props.original_subject_name, subject_tipo.clone()),
);
let mut sequence = vec![list_assign];
sequence.append(&mut air_elems);
(AirTree::void(), AirTree::UnhoistedSequence(sequence))
}
Pattern::Constructor { .. } => todo!(),
Pattern::Tuple { .. } => todo!(),
}

View File

@ -1,10 +1,6 @@
use std::sync::Arc;
use crate::{
ast::{Constant, Pattern, TypedClause},
gen_uplc::builder::{AssignmentProperties, ClauseProperties},
tipo::{PatternConstructor, Type},
};
use crate::{ast::Constant, tipo::Type};
use super::tree::AirTree;

View File

@ -1,5 +1,5 @@
use indexmap::IndexSet;
use std::{collections::VecDeque, sync::Arc};
use std::sync::Arc;
use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction};
use crate::{
@ -12,54 +12,20 @@ use super::air::Air;
#[derive(Debug, Clone, PartialEq)]
pub enum AirTree {
Statement(AirStatement),
Statement {
statement: AirStatement,
hoisted_over: Option<Box<AirTree>>,
},
Expression(AirExpression),
UnhoistedSequence(Vec<AirTree>),
}
pub struct AirIterator<'a> {
deque_pointer: VecDeque<&'a AirTree>,
}
impl Iterator for AirIterator<'_> {
type Item = Air;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
impl DoubleEndedIterator for AirIterator<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
todo!()
}
}
pub struct AirTreeIterator<'a> {
deque_pointer: VecDeque<&'a AirTree>,
}
impl<'a> Iterator for AirTreeIterator<'a> {
fn next(&mut self) -> Option<Self::Item> {
self.deque_pointer.pop_front()
}
type Item = &'a AirTree;
}
impl DoubleEndedIterator for AirTreeIterator<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.deque_pointer.pop_back()
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum AirStatement {
// Assignment
Let {
name: String,
value: Box<AirTree>,
hoisted_over: Option<Box<AirTree>>,
},
DefineFunc {
func_name: String,
@ -68,25 +34,21 @@ pub enum AirStatement {
recursive: bool,
variant_name: String,
func_body: Box<AirTree>,
hoisted_over: Option<Box<AirTree>>,
},
// Assertions
AssertConstr {
constr_index: usize,
constr: Box<AirTree>,
hoisted_over: Option<Box<AirTree>>,
},
AssertBool {
is_true: bool,
value: Box<AirTree>,
hoisted_over: Option<Box<AirTree>>,
},
// Field Access
FieldsExpose {
indices: Vec<(usize, String, Arc<Type>)>,
check_last_item: bool,
record: Box<AirTree>,
hoisted_over: Option<Box<AirTree>>,
},
// List Access
ListAccessor {
@ -95,14 +57,12 @@ pub enum AirStatement {
tail: bool,
check_last_item: bool,
list: Box<AirTree>,
hoisted_over: Option<Box<AirTree>>,
},
ListExpose {
tipo: Arc<Type>,
tail_head_names: Vec<(String, String)>,
tail: Option<(String, String)>,
list: Box<AirTree>,
hoisted_over: Option<Box<AirTree>>,
},
// Tuple Access
TupleAccessor {
@ -110,12 +70,9 @@ pub enum AirStatement {
tipo: Arc<Type>,
check_last_item: bool,
tuple: Box<AirTree>,
hoisted_over: Option<Box<AirTree>>,
},
// Misc.
NoOp {
hoisted_over: Option<Box<AirTree>>,
},
NoOp,
}
#[derive(Debug, Clone, PartialEq)]
@ -365,15 +322,17 @@ impl AirTree {
recursive: bool,
func_body: AirTree,
) -> AirTree {
AirTree::Statement(AirStatement::DefineFunc {
AirTree::Statement {
statement: AirStatement::DefineFunc {
func_name: func_name.to_string(),
module_name: module_name.to_string(),
params,
recursive,
variant_name: variant_name.to_string(),
func_body: func_body.into(),
},
hoisted_over: None,
})
}
}
pub fn anon_func(params: Vec<String>, func_body: AirTree) -> AirTree {
AirTree::Expression(AirExpression::Fn {
@ -399,11 +358,13 @@ impl AirTree {
})
}
pub fn let_assignment(name: impl ToString, value: AirTree) -> AirTree {
AirTree::Statement(AirStatement::Let {
AirTree::Statement {
statement: AirStatement::Let {
name: name.to_string(),
value: value.into(),
},
hoisted_over: None,
})
}
}
pub fn unwrap_data(value: AirTree, tipo: Arc<Type>) -> AirTree {
AirTree::Expression(AirExpression::UnWrapData {
@ -418,18 +379,22 @@ impl AirTree {
})
}
pub fn assert_constr_index(constr_index: usize, constr: AirTree) -> AirTree {
AirTree::Statement(AirStatement::AssertConstr {
AirTree::Statement {
statement: AirStatement::AssertConstr {
constr_index,
constr: constr.into(),
},
hoisted_over: None,
})
}
}
pub fn assert_bool(is_true: bool, value: AirTree) -> AirTree {
AirTree::Statement(AirStatement::AssertBool {
AirTree::Statement {
statement: AirStatement::AssertBool {
is_true,
value: value.into(),
},
hoisted_over: None,
})
}
}
pub fn when(subject_name: impl ToString, tipo: Arc<Type>, clauses: AirTree) -> AirTree {
AirTree::Expression(AirExpression::When {
@ -592,12 +557,14 @@ impl AirTree {
check_last_item: bool,
record: AirTree,
) -> AirTree {
AirTree::Statement(AirStatement::FieldsExpose {
AirTree::Statement {
statement: AirStatement::FieldsExpose {
indices,
check_last_item,
record: record.into(),
},
hoisted_over: None,
})
}
}
pub fn list_access(
names: Vec<String>,
@ -606,14 +573,16 @@ impl AirTree {
check_last_item: bool,
list: AirTree,
) -> AirTree {
AirTree::Statement(AirStatement::ListAccessor {
AirTree::Statement {
statement: AirStatement::ListAccessor {
tipo,
names,
tail,
check_last_item,
list: list.into(),
},
hoisted_over: None,
})
}
}
pub fn list_expose(
tail_head_names: Vec<(String, String)>,
@ -621,13 +590,15 @@ impl AirTree {
tipo: Arc<Type>,
list: AirTree,
) -> AirTree {
AirTree::Statement(AirStatement::ListExpose {
AirTree::Statement {
statement: AirStatement::ListExpose {
tipo,
tail_head_names,
tail,
list: list.into(),
},
hoisted_over: None,
})
}
}
pub fn tuple_access(
names: Vec<String>,
@ -635,13 +606,15 @@ impl AirTree {
check_last_item: bool,
tuple: AirTree,
) -> AirTree {
AirTree::Statement(AirStatement::TupleAccessor {
AirTree::Statement {
statement: AirStatement::TupleAccessor {
names,
tipo,
check_last_item,
tuple: tuple.into(),
},
hoisted_over: None,
})
}
}
pub fn tuple_index(tuple_index: usize, tipo: Arc<Type>, tuple: AirTree) -> AirTree {
AirTree::Expression(AirExpression::TupleIndex {
@ -661,7 +634,10 @@ impl AirTree {
})
}
pub fn no_op() -> AirTree {
AirTree::Statement(AirStatement::NoOp { hoisted_over: None })
AirTree::Statement {
statement: AirStatement::NoOp,
hoisted_over: None,
}
}
pub fn fields_empty(constr: AirTree) -> AirTree {
AirTree::Expression(AirExpression::FieldsEmpty {
@ -673,21 +649,12 @@ impl AirTree {
}
pub fn hoist_over(mut assignment: AirTree, next_exp: AirTree) -> AirTree {
match &mut assignment {
AirTree::Statement(st) => match st {
AirStatement::Let { hoisted_over, .. }
| AirStatement::AssertConstr { hoisted_over, .. }
| AirStatement::AssertBool { hoisted_over, .. }
| AirStatement::FieldsExpose { hoisted_over, .. }
| AirStatement::ListAccessor { hoisted_over, .. }
| AirStatement::NoOp { hoisted_over }
| AirStatement::ListExpose { hoisted_over, .. }
| AirStatement::TupleAccessor { hoisted_over, .. }
| AirStatement::DefineFunc { hoisted_over, .. } => {
AirTree::Statement { hoisted_over, .. } => {
assert!(hoisted_over.is_none());
*hoisted_over = Some(next_exp.into());
assignment
}
},
AirTree::Expression(_) => {
unreachable!("Trying to hoist an expression onto an expression.")
}
@ -731,7 +698,7 @@ impl AirTree {
"__list_to_check",
void(),
AirTree::void(),
next_call,
AirTree::hoist_over(assign, next_call),
None,
false,
);
@ -744,54 +711,44 @@ impl AirTree {
true,
list_clause,
)
// self.air.push(Air::DefineFunc {
// scope: self.scope.clone(),
// func_name: EXPECT_ON_LIST.to_string(),
// module_name: "".to_string(),
// params: vec!["__list_to_check".to_string(), "__check_with".to_string()],
// recursive: true,
// variant_name: "".to_string(),
// });
}
pub fn iter(&self) -> AirTreeIterator {
let mut new_vec = vec![];
self.create_iter(&mut new_vec);
AirTreeIterator {
deque_pointer: new_vec.into(),
}
}
pub fn air_iter(&self) -> AirIterator {
let mut new_vec = vec![];
self.create_iter(&mut new_vec);
AirIterator {
deque_pointer: new_vec.into(),
}
}
fn create_iter<'a>(&'a self, pointer_vec: &mut Vec<&'a AirTree>) {
fn to_vec(&self, air_vec: &mut Vec<Air>) {
match self {
AirTree::Statement(st) => match st {
AirStatement::Let {
value,
AirTree::Statement {
statement,
hoisted_over: Some(exp),
..
} => {
pointer_vec.push(self);
value.create_iter(pointer_vec);
exp.create_iter(pointer_vec);
match statement {
AirStatement::Let { value, name } => {
air_vec.push(Air::Let { name: name.clone() });
value.to_vec(air_vec);
}
AirStatement::DefineFunc {
func_name,
module_name,
params,
recursive,
variant_name,
func_body,
} => {
air_vec.push(Air::DefineFunc {
func_name: func_name.clone(),
module_name: module_name.clone(),
params: params.clone(),
recursive: *recursive,
variant_name: variant_name.clone(),
});
func_body.to_vec(air_vec);
}
AirStatement::DefineFunc { .. } => todo!(),
AirStatement::AssertConstr {
constr,
hoisted_over: Some(exp),
..
constr_index,
} => {
pointer_vec.push(self);
constr.create_iter(pointer_vec);
exp.create_iter(pointer_vec);
air_vec.push(Air::AssertConstr {
constr_index: *constr_index,
});
constr.to_vec(air_vec);
}
AirStatement::AssertBool { .. } => todo!(),
AirStatement::FieldsExpose { .. } => todo!(),
@ -799,128 +756,14 @@ impl AirTree {
AirStatement::ListExpose { .. } => todo!(),
AirStatement::TupleAccessor { .. } => todo!(),
AirStatement::NoOp { .. } => todo!(),
_ => unreachable!("FOUND UNHOISTED STATEMENT"),
},
};
exp.to_vec(air_vec);
}
AirTree::Expression(_) => todo!(),
AirTree::UnhoistedSequence(_) => {
unreachable!("SHOULD FIRST RESOLVE ALL UNHOISTED SEQUENCES")
}
}
}
pub fn convert_to_air(&self) -> Air {
match self {
AirTree::Statement(st) => match st {
AirStatement::Let {
name,
value,
hoisted_over: Some(exp),
} => Air::Let { name: name.clone() },
AirStatement::DefineFunc { .. } => todo!(),
AirStatement::AssertConstr {
constr_index,
constr,
hoisted_over: Some(exp),
} => Air::AssertConstr {
constr_index: *constr_index,
},
AirStatement::AssertBool {
is_true,
value,
hoisted_over: Some(exp),
} => Air::AssertBool { is_true: *is_true },
AirStatement::FieldsExpose {
indices,
check_last_item,
record,
hoisted_over: Some(exp),
} => Air::FieldsExpose {
indices: indices.clone(),
check_last_item: *check_last_item,
},
AirStatement::ListAccessor {
tipo,
names,
tail,
check_last_item,
list,
hoisted_over: Some(exp),
} => Air::ListAccessor {
tipo: tipo.clone(),
names: names.clone(),
tail: *tail,
check_last_item: *check_last_item,
},
AirStatement::ListExpose {
tipo,
tail_head_names,
tail,
list,
hoisted_over: Some(exp),
} => Air::ListExpose {
tipo: tipo.clone(),
tail_head_names: tail_head_names.clone(),
tail: tail.clone(),
},
AirStatement::TupleAccessor {
names,
tipo,
check_last_item,
tuple,
hoisted_over: Some(exp),
} => Air::TupleAccessor {
names: names.clone(),
tipo: tipo.clone(),
check_last_item: *check_last_item,
},
AirStatement::NoOp {
hoisted_over: Some(exp),
} => Air::NoOp,
_ => unreachable!("SHOULD NOT HAVE A HOISTED OVER RESOLVING TO NONE"),
},
AirTree::Expression(exp) => match exp {
AirExpression::Int { value } => Air::Int {
value: value.clone(),
},
AirExpression::String { value } => Air::String {
value: value.clone(),
},
AirExpression::ByteArray { bytes } => Air::ByteArray {
bytes: bytes.clone(),
},
AirExpression::Bool { value } => Air::Bool { value: *value },
AirExpression::List { .. } => todo!(),
AirExpression::Tuple { .. } => todo!(),
AirExpression::Void => todo!(),
AirExpression::Var { .. } => todo!(),
AirExpression::Call { .. } => todo!(),
AirExpression::Fn { .. } => todo!(),
AirExpression::Builtin { .. } => todo!(),
AirExpression::BinOp { .. } => todo!(),
AirExpression::UnOp { .. } => todo!(),
AirExpression::UnWrapData { .. } => todo!(),
AirExpression::WrapData { .. } => todo!(),
AirExpression::When { .. } => todo!(),
AirExpression::Clause { .. } => todo!(),
AirExpression::ListClause { .. } => todo!(),
AirExpression::WrapClause { .. } => todo!(),
AirExpression::TupleClause { .. } => todo!(),
AirExpression::ClauseGuard { .. } => todo!(),
AirExpression::ListClauseGuard { .. } => todo!(),
AirExpression::Finally { .. } => todo!(),
AirExpression::If { .. } => todo!(),
AirExpression::Constr { .. } => todo!(),
AirExpression::RecordUpdate { .. } => todo!(),
AirExpression::RecordAccess { .. } => todo!(),
AirExpression::TupleIndex { .. } => todo!(),
AirExpression::ErrorTerm { .. } => todo!(),
AirExpression::Trace { .. } => todo!(),
AirExpression::FieldsEmpty { .. } => todo!(),
AirExpression::ListEmpty { .. } => todo!(),
},
AirTree::UnhoistedSequence(_) => {
unreachable!("SHOULD FIRST RESOLVE ALL UNHOISTED SEQUENCES")
unreachable!("FIRST RESOLVE ALL UNHOISTED SEQUENCES")
}
_ => unreachable!("FOUND UNHOISTED STATEMENT"),
}
}
}