checkpoint

This commit is contained in:
microproofs 2023-07-01 01:09:26 -04:00 committed by Kasey
parent 0854d71836
commit f94c8213b6
6 changed files with 848 additions and 70 deletions

View File

@ -95,7 +95,10 @@ impl ClauseProperties {
original_subject_name: subject_name, original_subject_name: subject_name,
final_clause: false, final_clause: false,
needs_constr_var: false, needs_constr_var: false,
specific_clause: SpecificClause::ConstrClause, specific_clause: SpecificClause::ListClause {
current_index: 0,
defined_tails: vec![],
},
} }
} else if t.is_tuple() { } else if t.is_tuple() {
ClauseProperties { ClauseProperties {

View File

@ -21,8 +21,8 @@ use crate::{
gen_uplc::{ gen_uplc::{
air::Air, air::Air,
builder::{ builder::{
self as build, AssignmentProperties, ClauseProperties, DataTypeKey, FunctionAccessKey, self as build, lookup_data_type_by_tipo, AssignmentProperties, ClauseProperties,
SpecificClause, DataTypeKey, FunctionAccessKey, SpecificClause,
}, },
}, },
tipo::{ tipo::{
@ -91,8 +91,10 @@ impl<'a> CodeGenerator<'a> {
pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program<Name> { pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program<Name> {
let mut air_tree = self.build(test_body); let mut air_tree = self.build(test_body);
air_tree = AirTree::hoist_over(AirTree::no_op(), air_tree);
air_tree = AirTree::no_op().hoist_over(air_tree);
println!("{:#?}", air_tree); println!("{:#?}", air_tree);
println!("{:#?}", air_tree.to_vec());
todo!() todo!()
} }
@ -116,7 +118,7 @@ impl<'a> CodeGenerator<'a> {
while let Some(expression) = expressions.pop() { while let Some(expression) = expressions.pop() {
let exp_tree = self.build(&expression); let exp_tree = self.build(&expression);
last_exp = AirTree::hoist_over(exp_tree, last_exp); last_exp = exp_tree.hoist_over(last_exp);
} }
last_exp last_exp
} }
@ -309,7 +311,7 @@ impl<'a> CodeGenerator<'a> {
}, },
); );
AirTree::hoist_over(assignment, clause_then) assignment.hoist_over(clause_then)
} else { } else {
clauses = if subject.tipo().is_list() { clauses = if subject.tipo().is_list() {
build::rearrange_clauses(clauses) build::rearrange_clauses(clauses)
@ -343,9 +345,14 @@ impl<'a> CodeGenerator<'a> {
); );
let constr_assign = AirTree::let_assignment(&constr_var, self.build(subject)); let constr_assign = AirTree::let_assignment(&constr_var, self.build(subject));
let when_assign = AirTree::when(subject_name, subject.tipo(), clauses); let when_assign = AirTree::when(
subject_name,
subject.tipo(),
AirTree::local_var(constr_var, tipo.clone()),
clauses,
);
AirTree::hoist_over(constr_assign, when_assign) constr_assign.hoist_over(when_assign)
} }
} }
@ -511,7 +518,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::int(expected_int), AirTree::int(expected_int),
AirTree::local_var(name, int()), AirTree::local_var(name, int()),
); );
AirTree::assert_bool(true, AirTree::hoist_over(assignment, expect)) AirTree::assert_bool(true, assignment.hoist_over(expect))
} else { } else {
unreachable!("Code Gen should never reach here") unreachable!("Code Gen should never reach here")
} }
@ -524,13 +531,12 @@ impl<'a> CodeGenerator<'a> {
let val = AirTree::local_var(name, tipo.clone()); let val = AirTree::local_var(name, tipo.clone());
if tipo.is_primitive() { if tipo.is_primitive() {
AirTree::let_assignment(name, AirTree::hoist_over(assignment, val)) AirTree::let_assignment(name, assignment.hoist_over(val))
} else { } else {
let expect = let expect =
self.expect_type(tipo, val.clone(), &mut index_map, pattern.location()); self.expect_type(tipo, val.clone(), &mut index_map, pattern.location());
let assign = let assign = AirTree::let_assignment("_", assignment.hoist_over(expect));
AirTree::let_assignment("_", AirTree::hoist_over(assignment, expect)); AirTree::let_assignment(name, assign.hoist_over(val))
AirTree::let_assignment(name, AirTree::hoist_over(assign, val))
} }
} else { } else {
AirTree::let_assignment(name, value) AirTree::let_assignment(name, value)
@ -551,13 +557,12 @@ impl<'a> CodeGenerator<'a> {
let assignment = AirTree::let_assignment(name, value); let assignment = AirTree::let_assignment(name, value);
let val = AirTree::local_var(name, tipo.clone()); let val = AirTree::local_var(name, tipo.clone());
if tipo.is_primitive() { if tipo.is_primitive() {
AirTree::let_assignment(name, AirTree::hoist_over(assignment, val)) AirTree::let_assignment(name, assignment.hoist_over(val))
} else { } else {
let expect = let expect =
self.expect_type(tipo, val.clone(), &mut index_map, pattern.location()); self.expect_type(tipo, val.clone(), &mut index_map, pattern.location());
let assign = let assign = AirTree::let_assignment("_", assignment.hoist_over(expect));
AirTree::let_assignment("_", AirTree::hoist_over(assignment, expect)); AirTree::let_assignment(name, assign.hoist_over(val))
AirTree::let_assignment(name, AirTree::hoist_over(assign, val))
} }
} else if !props.remove_unused { } else if !props.remove_unused {
AirTree::let_assignment(name, value) AirTree::let_assignment(name, value)
@ -653,7 +658,6 @@ impl<'a> CodeGenerator<'a> {
}, },
), ),
)); ));
println!("ELEMS IS {:#?}", elems);
}); });
let names = elems.iter().map(|(name, _)| name.to_string()).collect_vec(); let names = elems.iter().map(|(name, _)| name.to_string()).collect_vec();
@ -801,7 +805,7 @@ impl<'a> CodeGenerator<'a> {
// This `value` is either value param that was passed in or // This `value` is either value param that was passed in or
// local var // local var
sequence.push(AirTree::fields_expose(indices, false, value)); sequence.push(AirTree::fields_expose(indices, props.full_check, value));
sequence.append( sequence.append(
&mut fields &mut fields
@ -877,7 +881,12 @@ impl<'a> CodeGenerator<'a> {
// This `value` is either value param that was passed in or // This `value` is either value param that was passed in or
// local var // local var
sequence.push(AirTree::tuple_access(indices, tipo.clone(), false, value)); sequence.push(AirTree::tuple_access(
indices,
tipo.clone(),
props.full_check,
value,
));
sequence.append(&mut elems.into_iter().map(|(_, field)| field).collect_vec()); sequence.append(&mut elems.into_iter().map(|(_, field)| field).collect_vec());
@ -930,14 +939,12 @@ impl<'a> CodeGenerator<'a> {
location, location,
); );
let anon_func_body = AirTree::hoist_over( let anon_func_body = AirTree::UnhoistedSequence(vec![
AirTree::UnhoistedSequence(vec![
tuple_access, tuple_access,
AirTree::let_assignment("_", expect_fst), AirTree::let_assignment("_", expect_fst),
AirTree::let_assignment("_", expect_snd), AirTree::let_assignment("_", expect_snd),
]), ])
AirTree::void(), .hoist_over(AirTree::void());
);
let unwrap_function = AirTree::anon_func(vec![pair_name], anon_func_body); let unwrap_function = AirTree::anon_func(vec![pair_name], anon_func_body);
@ -963,7 +970,7 @@ impl<'a> CodeGenerator<'a> {
vec![AirTree::local_var(map_name, tipo.clone()), unwrap_function], vec![AirTree::local_var(map_name, tipo.clone()), unwrap_function],
); );
AirTree::hoist_over(assign, func_call) assign.hoist_over(func_call)
} else if tipo.is_list() { } else if tipo.is_list() {
assert!(!tipo.get_inner_types().is_empty()); assert!(!tipo.get_inner_types().is_empty());
let inner_list_type = &tipo.get_inner_types()[0]; let inner_list_type = &tipo.get_inner_types()[0];
@ -981,7 +988,7 @@ impl<'a> CodeGenerator<'a> {
); );
let anon_func_body = let anon_func_body =
AirTree::hoist_over(AirTree::let_assignment("_", expect_item), AirTree::void()); AirTree::let_assignment("_", expect_item).hoist_over(AirTree::void());
let unwrap_function = AirTree::anon_func(vec![item_name], anon_func_body); let unwrap_function = AirTree::anon_func(vec![item_name], anon_func_body);
@ -1007,9 +1014,86 @@ impl<'a> CodeGenerator<'a> {
vec![AirTree::local_var(list_name, tipo.clone()), unwrap_function], vec![AirTree::local_var(list_name, tipo.clone()), unwrap_function],
); );
AirTree::hoist_over(assign, func_call) assign.hoist_over(func_call)
} else { } else if tipo.is_2_tuple() {
let tuple_inner_types = tipo.get_inner_types();
let pair_name = format!("__pair_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 tuple_assign = AirTree::let_assignment(&pair_name, value);
let tuple_access = AirTree::tuple_access(
vec![fst_name.clone(), snd_name.clone()],
tipo.clone(),
false,
AirTree::local_var(pair_name, tipo.clone()),
);
let expect_fst = self.expect_type(
&tuple_inner_types[0],
AirTree::local_var(fst_name, tuple_inner_types[0].clone()),
defined_data_types,
location,
);
let expect_snd = self.expect_type(
&tuple_inner_types[1],
AirTree::local_var(snd_name, tuple_inner_types[1].clone()),
defined_data_types,
location,
);
AirTree::UnhoistedSequence(vec![
tuple_assign,
tuple_access,
AirTree::let_assignment("_", expect_fst),
AirTree::let_assignment("_", expect_snd),
])
.hoist_over(AirTree::void())
} else if tipo.is_tuple() {
todo!() todo!()
} else {
let data_type =
build::lookup_data_type_by_tipo(&self.data_types, tipo).unwrap_or_else(|| {
unreachable!("We need a data type definition fot type {:#?}", tipo)
});
// for (index, arg) in tipo.arg_types().unwrap().iter().enumerate() {
// let field_type = arg.clone();
// type_map.insert(index, field_type);
// }
// TODO calculate the variant name.
let data_type_name = format!("__expect_{}{}", data_type.name, "");
let function = self.code_gen_functions.get(&data_type_name);
if function.is_none() && defined_data_types.get(&data_type_name).is_none() {
todo!()
} else if let Some(counter) = defined_data_types.get_mut(&data_type_name) {
*counter += 1;
} else {
defined_data_types.insert(data_type_name.to_string(), 0);
}
let func_var = AirTree::var(
ValueConstructor::public(
tipo.clone(),
ValueConstructorVariant::ModuleFn {
name: data_type_name.to_string(),
field_map: None,
module: "".to_string(),
arity: 1,
location: Span::empty(),
builtin: None,
},
),
data_type_name,
"",
);
AirTree::call(func_var, void(), vec![value])
} }
} }
@ -1020,19 +1104,177 @@ impl<'a> CodeGenerator<'a> {
subject_tipo: &Arc<Type>, subject_tipo: &Arc<Type>,
props: &mut ClauseProperties, props: &mut ClauseProperties,
) -> AirTree { ) -> AirTree {
assert!(!clauses.is_empty()); assert!(
!subject_tipo.is_void(),
"WHY ARE YOU PATTERN MATCHING VOID???"
);
props.complex_clause = false; props.complex_clause = false;
if let Some((clause, rest_clauses)) = clauses.split_first() { if let Some((clause, rest_clauses)) = clauses.split_first() {
todo!() let mut clause_then = self.build(&clause.then);
if let Some(guard) = &clause.guard {
props.complex_clause = true;
let clause_guard_name = format!(
"__clause_guard_span_{}_{}",
clause.location.start, clause.location.end
);
let clause_guard_assign =
AirTree::let_assignment(clause_guard_name, builder::handle_clause_guard(guard));
clause_then = clause_guard_assign.hoist_over(clause_then);
}
match &mut props.specific_clause {
SpecificClause::ConstrClause => {
let data_type = build::lookup_data_type_by_tipo(&self.data_types, subject_tipo);
let (clause_cond, clause_assign) =
self.clause_pattern(&clause.pattern, subject_tipo, props);
let clause_assign_hoisted = clause_assign.hoist_over(clause_then);
let complex_clause = props.complex_clause;
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: props.specific_clause.clone(),
};
if let Some(data_type) = data_type {
if data_type.constructors.len() > 1 {
AirTree::clause(
&props.original_subject_name,
clause_cond,
subject_tipo.clone(),
clause_assign_hoisted,
self.handle_each_clause(
rest_clauses,
final_clause,
subject_tipo,
&mut next_clause_props,
),
complex_clause,
)
} else {
AirTree::wrap_clause(
clause_assign_hoisted,
self.handle_each_clause(
rest_clauses,
final_clause,
subject_tipo,
&mut next_clause_props,
),
)
}
} else {
AirTree::clause(
&props.original_subject_name,
clause_cond,
subject_tipo.clone(),
clause_assign_hoisted,
self.handle_each_clause(
rest_clauses,
final_clause,
subject_tipo,
&mut next_clause_props,
),
complex_clause,
)
}
}
SpecificClause::ListClause {
current_index,
defined_tails,
} => {
let Pattern::List { elements, .. } = &clause.pattern
else { unreachable!() };
let tail_name = if *current_index == 0 {
props.original_subject_name.clone()
} else {
format!(
"tail_index_{}_span_{}_{}",
*current_index,
clause.pattern.location().start,
clause.pattern.location().end
)
};
let next_tail_name = {
let next_elements_len = match &rest_clauses[0].pattern {
Pattern::List { elements, .. } => elements.len(),
_ => 0,
};
if (*current_index as usize) < next_elements_len {
Some(format!(
"tail_index_{}_span_{}_{}",
*current_index,
rest_clauses[0].pattern.location().start,
rest_clauses[0].pattern.location().end
))
} else {
None
}
};
if elements.len() > *current_index as usize {
*current_index += 1;
defined_tails.push(tail_name.clone());
}
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::ListClause {
current_index: *current_index,
defined_tails: defined_tails.clone(),
},
};
let (_, clause_assign) =
self.clause_pattern(&clause.pattern, subject_tipo, props);
let clause_assign_hoisted = clause_assign.hoist_over(clause_then);
let complex_clause = props.complex_clause;
AirTree::list_clause(
tail_name,
subject_tipo.clone(),
clause_assign_hoisted,
self.handle_each_clause(
clauses,
final_clause,
subject_tipo,
&mut next_clause_props,
),
next_tail_name,
complex_clause,
);
todo!();
}
SpecificClause::TupleClause { .. } => todo!(),
}
} else { } else {
// handle final_clause // handle final_clause
props.final_clause = true; props.final_clause = true;
assert!(final_clause.guard.is_none()); assert!(final_clause.guard.is_none());
let clause_then = self.build(&final_clause.then); let clause_then = self.build(&final_clause.then);
let (_, assignments) = self.clause_pattern(&final_clause.pattern, subject_tipo, props); let (condition, assignments) =
self.clause_pattern(&final_clause.pattern, subject_tipo, props);
AirTree::hoist_over(assignments, clause_then) AirTree::finally(condition, assignments.hoist_over(clause_then))
} }
} }
@ -1072,18 +1314,13 @@ impl<'a> CodeGenerator<'a> {
Pattern::Discard { .. } => (AirTree::void(), AirTree::no_op()), Pattern::Discard { .. } => (AirTree::void(), AirTree::no_op()),
Pattern::List { elements, tail, .. } => { Pattern::List { elements, tail, .. } => {
let ClauseProperties { let ClauseProperties {
specific_clause: specific_clause: SpecificClause::ListClause { defined_tails, .. },
SpecificClause::ListClause { complex_clause,
current_index: _,
defined_tails,
},
clause_var_name: _,
complex_clause: _,
needs_constr_var: _,
original_subject_name: _, original_subject_name: _,
final_clause: _, final_clause: _,
..
} = props } = props
else { unreachable!()}; else { unreachable!() };
let list_elem_types = subject_tipo.get_inner_types(); let list_elem_types = subject_tipo.get_inner_types();
@ -1116,7 +1353,7 @@ impl<'a> CodeGenerator<'a> {
let statement = let statement =
self.nested_clause_condition(elem, list_elem_type, &mut elem_props); self.nested_clause_condition(elem, list_elem_type, &mut elem_props);
props.complex_clause = props.complex_clause || elem_props.complex_clause; *complex_clause = *complex_clause || elem_props.complex_clause;
(tail, elem_name, statement) (tail, elem_name, statement)
}) })
@ -1164,7 +1401,7 @@ impl<'a> CodeGenerator<'a> {
let statement = let statement =
self.nested_clause_condition(elem, subject_tipo, &mut elem_props); self.nested_clause_condition(elem, subject_tipo, &mut elem_props);
props.complex_clause = props.complex_clause || elem_props.complex_clause; *complex_clause = *complex_clause || elem_props.complex_clause;
air_elems.push(statement); air_elems.push(statement);
list_tail = Some((tail.to_string(), elem_name)); list_tail = Some((tail.to_string(), elem_name));
@ -1183,7 +1420,123 @@ impl<'a> CodeGenerator<'a> {
(AirTree::void(), AirTree::UnhoistedSequence(sequence)) (AirTree::void(), AirTree::UnhoistedSequence(sequence))
} }
Pattern::Constructor { .. } => todo!(), Pattern::Constructor {
name,
arguments,
constructor,
..
} => {
if subject_tipo.is_bool() {
(AirTree::bool(name == "True"), AirTree::no_op())
} else {
let data_type = build::lookup_data_type_by_tipo(&self.data_types, subject_tipo)
.unwrap_or_else(|| {
unreachable!(
"Code Gen should have the definition for this constructor {}",
name
)
});
assert!(!data_type.constructors.is_empty());
let (constr_index, _) = data_type
.constructors
.iter()
.enumerate()
.find(|(_, dt)| &dt.name == name)
.unwrap();
let field_map = match constructor {
PatternConstructor::Record { field_map, .. } => field_map.clone(),
};
let mut type_map: IndexMap<usize, Arc<Type>> = IndexMap::new();
println!("tipo is {subject_tipo:#?}");
for (index, arg) in subject_tipo.arg_types().unwrap().iter().enumerate() {
let field_type = arg.clone();
type_map.insert(index, field_type);
}
let fields = arguments
.iter()
.enumerate()
.map(|(index, arg)| {
let label = arg.label.clone().unwrap_or_default();
let field_index = if let Some(field_map) = &field_map {
*field_map.fields.get(&label).map(|x| &x.0).unwrap_or(&index)
} else {
index
};
let field_name = match &arg.value {
Pattern::Var { name, .. } => name.to_string(),
Pattern::Assign { name, .. } => name.to_string(),
Pattern::Discard { .. } => "_".to_string(),
_ => format!(
"field_{}_span_{}_{}",
field_index,
arg.value.location().start,
arg.value.location().end
),
};
let arg_type = type_map.get(&field_index).unwrap_or_else(|| {
unreachable!(
"Missing type for field {} of constr {}",
field_index, name
)
});
let mut field_props = ClauseProperties {
clause_var_name: field_name.clone(),
complex_clause: false,
needs_constr_var: false,
original_subject_name: field_name.clone(),
final_clause: props.final_clause,
specific_clause: props.specific_clause.clone(),
};
let statement = self.nested_clause_condition(
&arg.value,
arg_type,
&mut field_props,
);
props.complex_clause =
props.complex_clause || field_props.complex_clause;
(field_index, field_name, arg_type, statement)
})
.collect_vec();
let indices = fields
.iter()
.map(|(constr_index, name, tipo, _)| {
(*constr_index, name.to_string(), (*tipo).clone())
})
.collect_vec();
let mut air_fields = fields.into_iter().map(|(_, _, _, val)| val).collect_vec();
let field_assign = AirTree::fields_expose(
indices,
false,
AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()),
);
let mut sequence = vec![field_assign];
sequence.append(&mut air_fields);
(
AirTree::int(constr_index),
AirTree::UnhoistedSequence(sequence),
)
}
}
Pattern::Tuple { .. } => todo!(), Pattern::Tuple { .. } => todo!(),
} }
} }

View File

@ -97,7 +97,7 @@ pub enum Air {
next_tail_name: Option<String>, next_tail_name: Option<String>,
complex_clause: bool, complex_clause: bool,
}, },
WrapClause {}, WrapClause,
TupleClause { TupleClause {
tipo: Arc<Type>, tipo: Arc<Type>,
indices: IndexSet<(usize, String)>, indices: IndexSet<(usize, String)>,
@ -122,7 +122,7 @@ pub enum Air {
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
// Record Creation // Record Creation
Record { Constr {
tag: usize, tag: usize,
tipo: Arc<Type>, tipo: Arc<Type>,
count: usize, count: usize,
@ -246,7 +246,7 @@ impl Air {
| Air::ClauseGuard { tipo, .. } | Air::ClauseGuard { tipo, .. }
| Air::If { tipo, .. } | Air::If { tipo, .. }
| Air::ListClauseGuard { tipo, .. } | Air::ListClauseGuard { tipo, .. }
| Air::Record { tipo, .. } | Air::Constr { tipo, .. }
| Air::RecordUpdate { tipo, .. } | Air::RecordUpdate { tipo, .. }
| Air::RecordAccess { tipo, .. } | Air::RecordAccess { tipo, .. }
| Air::ListAccessor { tipo, .. } | Air::ListAccessor { tipo, .. }

View File

@ -1,6 +1,10 @@
use crate::builtins::bool;
use std::sync::Arc; use std::sync::Arc;
use crate::{ast::Constant, tipo::Type}; use crate::{
ast::{BinOp, ClauseGuard, Constant, UnOp},
tipo::Type,
};
use super::tree::AirTree; use super::tree::AirTree;
@ -15,3 +19,63 @@ pub fn constants_ir(literal: &Constant) -> AirTree {
Constant::ByteArray { bytes, .. } => AirTree::byte_array(bytes.clone()), Constant::ByteArray { bytes, .. } => AirTree::byte_array(bytes.clone()),
} }
} }
pub fn handle_clause_guard(clause_guard: &ClauseGuard<Arc<Type>>) -> AirTree {
match clause_guard {
ClauseGuard::Not { value, .. } => {
let val = handle_clause_guard(value);
AirTree::unop(UnOp::Not, val)
}
ClauseGuard::Equals { left, right, .. } => {
let left = handle_clause_guard(left);
let right = handle_clause_guard(right);
AirTree::binop(BinOp::Eq, bool(), left, right)
}
ClauseGuard::NotEquals { left, right, .. } => {
let left = handle_clause_guard(left);
let right = handle_clause_guard(right);
AirTree::binop(BinOp::NotEq, bool(), left, right)
}
ClauseGuard::GtInt { left, right, .. } => {
let left = handle_clause_guard(left);
let right = handle_clause_guard(right);
AirTree::binop(BinOp::GtInt, bool(), left, right)
}
ClauseGuard::GtEqInt { left, right, .. } => {
let left = handle_clause_guard(left);
let right = handle_clause_guard(right);
AirTree::binop(BinOp::GtEqInt, bool(), left, right)
}
ClauseGuard::LtInt { left, right, .. } => {
let left = handle_clause_guard(left);
let right = handle_clause_guard(right);
AirTree::binop(BinOp::LtInt, bool(), left, right)
}
ClauseGuard::LtEqInt { left, right, .. } => {
let left = handle_clause_guard(left);
let right = handle_clause_guard(right);
AirTree::binop(BinOp::LtEqInt, bool(), left, right)
}
ClauseGuard::Or { left, right, .. } => {
let left = handle_clause_guard(left);
let right = handle_clause_guard(right);
AirTree::binop(BinOp::Or, bool(), left, right)
}
ClauseGuard::And { left, right, .. } => {
let left = handle_clause_guard(left);
let right = handle_clause_guard(right);
AirTree::binop(BinOp::And, bool(), left, right)
}
ClauseGuard::Var { tipo, name, .. } => AirTree::local_var(name, tipo.clone()),
ClauseGuard::Constant(constant) => constants_ir(constant),
}
}

View File

@ -5,6 +5,7 @@ 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},
}; };
@ -146,6 +147,7 @@ pub enum AirExpression {
When { When {
tipo: Arc<Type>, tipo: Arc<Type>,
subject_name: String, subject_name: String,
subject: Box<AirTree>,
clauses: Box<AirTree>, clauses: Box<AirTree>,
}, },
Clause { Clause {
@ -396,10 +398,16 @@ impl AirTree {
hoisted_over: None, hoisted_over: None,
} }
} }
pub fn when(subject_name: impl ToString, tipo: Arc<Type>, clauses: AirTree) -> AirTree { pub fn when(
subject_name: impl ToString,
tipo: Arc<Type>,
subject: AirTree,
clauses: AirTree,
) -> AirTree {
AirTree::Expression(AirExpression::When { AirTree::Expression(AirExpression::When {
tipo, tipo,
subject_name: subject_name.to_string(), subject_name: subject_name.to_string(),
subject: subject.into(),
clauses: clauses.into(), clauses: clauses.into(),
}) })
} }
@ -647,12 +655,12 @@ impl AirTree {
pub fn list_empty(list: AirTree) -> AirTree { pub fn list_empty(list: AirTree) -> AirTree {
AirTree::Expression(AirExpression::ListEmpty { list: list.into() }) AirTree::Expression(AirExpression::ListEmpty { list: list.into() })
} }
pub fn hoist_over(mut assignment: AirTree, next_exp: AirTree) -> AirTree { pub fn hoist_over(mut self, next_exp: AirTree) -> AirTree {
match &mut assignment { match &mut self {
AirTree::Statement { hoisted_over, .. } => { AirTree::Statement { hoisted_over, .. } => {
assert!(hoisted_over.is_none()); assert!(hoisted_over.is_none());
*hoisted_over = Some(next_exp.into()); *hoisted_over = Some(next_exp.into());
assignment self
} }
AirTree::Expression(_) => { AirTree::Expression(_) => {
@ -661,7 +669,7 @@ impl AirTree {
AirTree::UnhoistedSequence(seq) => { AirTree::UnhoistedSequence(seq) => {
let mut final_exp = next_exp; let mut final_exp = next_exp;
while let Some(assign) = seq.pop() { while let Some(assign) = seq.pop() {
final_exp = Self::hoist_over(assign, final_exp); final_exp = assign.hoist_over(final_exp);
} }
final_exp final_exp
} }
@ -698,7 +706,7 @@ impl AirTree {
"__list_to_check", "__list_to_check",
void(), void(),
AirTree::void(), AirTree::void(),
AirTree::hoist_over(assign, next_call), assign.hoist_over(next_call),
None, None,
false, false,
); );
@ -713,7 +721,13 @@ impl AirTree {
) )
} }
fn to_vec(&self, air_vec: &mut Vec<Air>) { pub fn to_vec(&self) -> Vec<Air> {
let mut air_vec = vec![];
self.create_air_vec(&mut air_vec);
air_vec
}
fn create_air_vec(&self, air_vec: &mut Vec<Air>) {
match self { match self {
AirTree::Statement { AirTree::Statement {
statement, statement,
@ -722,7 +736,7 @@ impl AirTree {
match statement { match statement {
AirStatement::Let { value, name } => { AirStatement::Let { value, name } => {
air_vec.push(Air::Let { name: name.clone() }); air_vec.push(Air::Let { name: name.clone() });
value.to_vec(air_vec); value.create_air_vec(air_vec);
} }
AirStatement::DefineFunc { AirStatement::DefineFunc {
func_name, func_name,
@ -739,7 +753,7 @@ impl AirTree {
recursive: *recursive, recursive: *recursive,
variant_name: variant_name.clone(), variant_name: variant_name.clone(),
}); });
func_body.to_vec(air_vec); func_body.create_air_vec(air_vec);
} }
AirStatement::AssertConstr { AirStatement::AssertConstr {
constr, constr,
@ -748,18 +762,347 @@ impl AirTree {
air_vec.push(Air::AssertConstr { air_vec.push(Air::AssertConstr {
constr_index: *constr_index, constr_index: *constr_index,
}); });
constr.to_vec(air_vec); constr.create_air_vec(air_vec);
}
AirStatement::AssertBool { is_true, value } => {
air_vec.push(Air::AssertBool { is_true: *is_true });
value.create_air_vec(air_vec);
}
AirStatement::FieldsExpose {
indices,
check_last_item,
record,
} => {
air_vec.push(Air::FieldsExpose {
indices: indices.clone(),
check_last_item: *check_last_item,
});
record.create_air_vec(air_vec);
}
AirStatement::ListAccessor {
tipo,
names,
tail,
check_last_item,
list,
} => {
air_vec.push(Air::ListAccessor {
tipo: tipo.clone(),
names: names.clone(),
tail: *tail,
check_last_item: *check_last_item,
});
list.create_air_vec(air_vec);
}
AirStatement::ListExpose {
tipo,
tail_head_names,
tail,
list,
} => {
air_vec.push(Air::ListExpose {
tipo: tipo.clone(),
tail_head_names: tail_head_names.clone(),
tail: tail.clone(),
});
list.create_air_vec(air_vec);
}
AirStatement::TupleAccessor {
names,
tipo,
check_last_item,
tuple,
} => {
air_vec.push(Air::TupleAccessor {
names: names.clone(),
tipo: tipo.clone(),
check_last_item: *check_last_item,
});
tuple.create_air_vec(air_vec);
}
AirStatement::NoOp => {
air_vec.push(Air::NoOp);
} }
AirStatement::AssertBool { .. } => todo!(),
AirStatement::FieldsExpose { .. } => todo!(),
AirStatement::ListAccessor { .. } => todo!(),
AirStatement::ListExpose { .. } => todo!(),
AirStatement::TupleAccessor { .. } => todo!(),
AirStatement::NoOp { .. } => todo!(),
}; };
exp.to_vec(air_vec); exp.create_air_vec(air_vec);
} }
AirTree::Expression(_) => todo!(), AirTree::Expression(exp) => match exp {
AirExpression::Int { value } => air_vec.push(Air::Int {
value: value.clone(),
}),
AirExpression::String { value } => air_vec.push(Air::String {
value: value.clone(),
}),
AirExpression::ByteArray { bytes } => air_vec.push(Air::ByteArray {
bytes: bytes.clone(),
}),
AirExpression::Bool { value } => air_vec.push(Air::Bool { value: *value }),
AirExpression::List { tipo, tail, items } => {
air_vec.push(Air::List {
count: items.len(),
tipo: tipo.clone(),
tail: *tail,
});
for item in items {
item.create_air_vec(air_vec);
}
}
AirExpression::Tuple { tipo, items } => {
air_vec.push(Air::Tuple {
tipo: tipo.clone(),
count: items.len(),
});
for item in items {
item.create_air_vec(air_vec);
}
}
AirExpression::Void => air_vec.push(Air::Void),
AirExpression::Var {
constructor,
name,
variant_name,
} => air_vec.push(Air::Var {
constructor: constructor.clone(),
name: name.clone(),
variant_name: variant_name.clone(),
}),
AirExpression::Call { tipo, func, args } => {
air_vec.push(Air::Call {
count: args.len(),
tipo: tipo.clone(),
});
func.create_air_vec(air_vec);
for arg in args {
arg.create_air_vec(air_vec);
}
}
AirExpression::Fn { params, func_body } => {
air_vec.push(Air::Fn {
params: params.clone(),
});
func_body.create_air_vec(air_vec);
}
AirExpression::Builtin { func, tipo, args } => {
air_vec.push(Air::Builtin {
count: args.len(),
func: *func,
tipo: tipo.clone(),
});
for arg in args {
arg.create_air_vec(air_vec);
}
}
AirExpression::BinOp {
name,
tipo,
left,
right,
} => {
air_vec.push(Air::BinOp {
name: name.clone(),
tipo: tipo.clone(),
});
left.create_air_vec(air_vec);
right.create_air_vec(air_vec);
}
AirExpression::UnOp { op, arg } => {
air_vec.push(Air::UnOp { op: *op });
arg.create_air_vec(air_vec);
}
AirExpression::UnWrapData { tipo, value } => {
air_vec.push(Air::UnWrapData { tipo: tipo.clone() });
value.create_air_vec(air_vec);
}
AirExpression::WrapData { tipo, value } => {
air_vec.push(Air::WrapData { tipo: tipo.clone() });
value.create_air_vec(air_vec);
}
AirExpression::When {
tipo,
subject_name,
subject,
clauses,
} => {
air_vec.push(Air::When {
tipo: tipo.clone(),
subject_name: subject_name.clone(),
});
subject.create_air_vec(air_vec);
clauses.create_air_vec(air_vec);
}
AirExpression::Clause {
tipo,
subject_name,
complex_clause,
pattern,
then,
otherwise,
} => {
air_vec.push(Air::Clause {
tipo: tipo.clone(),
subject_name: subject_name.clone(),
complex_clause: *complex_clause,
});
pattern.create_air_vec(air_vec);
then.create_air_vec(air_vec);
otherwise.create_air_vec(air_vec);
}
AirExpression::ListClause {
tipo,
tail_name,
next_tail_name,
complex_clause,
then,
otherwise,
} => {
air_vec.push(Air::ListClause {
tipo: tipo.clone(),
tail_name: tail_name.clone(),
next_tail_name: next_tail_name.clone(),
complex_clause: *complex_clause,
});
then.create_air_vec(air_vec);
otherwise.create_air_vec(air_vec);
}
AirExpression::WrapClause { then, otherwise } => {
air_vec.push(Air::WrapClause);
then.create_air_vec(air_vec);
otherwise.create_air_vec(air_vec);
}
AirExpression::TupleClause {
tipo,
indices,
predefined_indices,
subject_name,
type_count,
complex_clause,
then,
otherwise,
} => {
air_vec.push(Air::TupleClause {
tipo: tipo.clone(),
indices: indices.clone(),
predefined_indices: predefined_indices.clone(),
subject_name: subject_name.clone(),
count: *type_count,
complex_clause: *complex_clause,
});
then.create_air_vec(air_vec);
otherwise.create_air_vec(air_vec);
}
AirExpression::ClauseGuard {
subject_name,
tipo,
pattern,
then,
} => {
air_vec.push(Air::ClauseGuard {
subject_name: subject_name.clone(),
tipo: tipo.clone(),
});
pattern.create_air_vec(air_vec);
then.create_air_vec(air_vec);
}
AirExpression::ListClauseGuard {
tipo,
tail_name,
next_tail_name,
inverse,
then,
} => {
air_vec.push(Air::ListClauseGuard {
tipo: tipo.clone(),
tail_name: tail_name.clone(),
next_tail_name: next_tail_name.clone(),
inverse: *inverse,
});
then.create_air_vec(air_vec);
}
AirExpression::Finally { pattern, then } => {
air_vec.push(Air::Finally);
pattern.create_air_vec(air_vec);
then.create_air_vec(air_vec);
}
AirExpression::If {
tipo,
pattern,
then,
otherwise,
} => {
air_vec.push(Air::If { tipo: tipo.clone() });
pattern.create_air_vec(air_vec);
then.create_air_vec(air_vec);
otherwise.create_air_vec(air_vec);
}
AirExpression::Constr { tag, tipo, args } => {
air_vec.push(Air::Constr {
tag: *tag,
tipo: tipo.clone(),
count: args.len(),
});
for arg in args {
arg.create_air_vec(air_vec);
}
}
AirExpression::RecordUpdate {
highest_index,
indices,
tipo,
record,
args,
} => {
air_vec.push(Air::RecordUpdate {
highest_index: *highest_index,
indices: indices.clone(),
tipo: tipo.clone(),
});
record.create_air_vec(air_vec);
for arg in args {
arg.create_air_vec(air_vec);
}
}
AirExpression::RecordAccess {
field_index,
tipo,
record,
} => {
air_vec.push(Air::RecordAccess {
record_index: *field_index,
tipo: tipo.clone(),
});
record.create_air_vec(air_vec);
}
AirExpression::TupleIndex {
tipo,
tuple_index,
tuple,
} => {
air_vec.push(Air::TupleIndex {
tipo: tipo.clone(),
tuple_index: *tuple_index,
});
tuple.create_air_vec(air_vec);
}
AirExpression::ErrorTerm { tipo } => {
air_vec.push(Air::ErrorTerm { tipo: tipo.clone() })
}
AirExpression::Trace { tipo, msg, then } => {
air_vec.push(Air::Trace { tipo: tipo.clone() });
msg.create_air_vec(air_vec);
then.create_air_vec(air_vec);
}
AirExpression::FieldsEmpty { constr } => {
air_vec.push(Air::FieldsEmpty);
constr.create_air_vec(air_vec);
}
AirExpression::ListEmpty { list } => {
air_vec.push(Air::ListEmpty);
list.create_air_vec(air_vec);
}
},
AirTree::UnhoistedSequence(_) => { AirTree::UnhoistedSequence(_) => {
unreachable!("FIRST RESOLVE ALL UNHOISTED SEQUENCES") unreachable!("FIRST RESOLVE ALL UNHOISTED SEQUENCES")
} }

View File

@ -180,6 +180,14 @@ impl Type {
} }
} }
pub fn is_2_tuple(&self) -> bool {
match self {
Type::Var { tipo } => tipo.borrow().is_2_tuple(),
Type::Tuple { elems } => elems.len() == 2,
_ => false,
}
}
pub fn is_data(&self) -> bool { pub fn is_data(&self) -> bool {
match self { match self {
Self::App { module, name, .. } => "Data" == name && module.is_empty(), Self::App { module, name, .. } => "Data" == name && module.is_empty(),
@ -483,6 +491,13 @@ impl TypeVar {
} }
} }
pub fn is_2_tuple(&self) -> bool {
match self {
Self::Link { tipo } => tipo.is_2_tuple(),
_ => false,
}
}
pub fn is_data(&self) -> bool { pub fn is_data(&self) -> bool {
match self { match self {
Self::Link { tipo } => tipo.is_data(), Self::Link { tipo } => tipo.is_data(),