got past the errors and warnings

This commit is contained in:
microproofs 2024-02-04 16:35:32 -05:00 committed by Kasey
parent 51f1da2505
commit 6c6be3f53d
2 changed files with 252 additions and 252 deletions

View File

@ -50,7 +50,7 @@ use self::{
AssignmentProperties, ClauseProperties, CodeGenSpecialFuncs, CycleFunctionNames, AssignmentProperties, ClauseProperties, CodeGenSpecialFuncs, CycleFunctionNames,
DataTypeKey, FunctionAccessKey, HoistableFunction, Variant, DataTypeKey, FunctionAccessKey, HoistableFunction, Variant,
}, },
tree::{AirExpression, AirMsg, AirTree, TreePath}, tree::{AirMsg, AirTree, TreePath},
}; };
#[derive(Clone)] #[derive(Clone)]
@ -141,7 +141,7 @@ impl<'a> CodeGenerator<'a> {
let mut validator_args_tree = let mut validator_args_tree =
self.check_validator_args(&fun.arguments, true, air_tree_fun, &src_code, &lines); self.check_validator_args(&fun.arguments, true, air_tree_fun, &src_code, &lines);
validator_args_tree = AirTree::no_op().hoist_over(validator_args_tree); validator_args_tree = AirTree::no_op(validator_args_tree);
let full_tree = self.hoist_functions_to_validator(validator_args_tree); let full_tree = self.hoist_functions_to_validator(validator_args_tree);
@ -166,7 +166,7 @@ impl<'a> CodeGenerator<'a> {
&lines, &lines,
); );
validator_args_tree_other = AirTree::no_op().hoist_over(validator_args_tree_other); validator_args_tree_other = AirTree::no_op(validator_args_tree_other);
let full_tree_other = self.hoist_functions_to_validator(validator_args_tree_other); let full_tree_other = self.hoist_functions_to_validator(validator_args_tree_other);
@ -201,7 +201,7 @@ impl<'a> CodeGenerator<'a> {
pub fn generate_test(&mut self, test_body: &TypedExpr, module_name: &String) -> Program<Name> { pub fn generate_test(&mut self, test_body: &TypedExpr, module_name: &String) -> Program<Name> {
let mut air_tree = self.build(test_body, module_name, &[]); let mut air_tree = self.build(test_body, module_name, &[]);
air_tree = AirTree::no_op().hoist_over(air_tree); air_tree = AirTree::no_op(air_tree);
let full_tree = self.hoist_functions_to_validator(air_tree); let full_tree = self.hoist_functions_to_validator(air_tree);
@ -849,9 +849,7 @@ impl<'a> CodeGenerator<'a> {
) -> AirTree { ) -> AirTree {
assert!( assert!(
match &value { match &value {
AirTree::Expression(AirExpression::Var { name, .. }) AirTree::Var { name, .. } if props.kind == AssignmentKind::Let => {
if props.kind == AssignmentKind::Let =>
{
name != "_" name != "_"
} }
_ => true, _ => true,
@ -889,7 +887,7 @@ impl<'a> CodeGenerator<'a> {
let expr = AirTree::let_assignment(name, value, expect); let expr = AirTree::let_assignment(name, value, expect);
AirTree::assert_bool(true, expr, props.msg_func.clone()).hoist_over(then) AirTree::assert_bool(true, expr, props.msg_func.clone(), then)
} }
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
@ -956,7 +954,7 @@ impl<'a> CodeGenerator<'a> {
} else if !props.remove_unused { } else if !props.remove_unused {
AirTree::let_assignment(name, value, then) AirTree::let_assignment(name, value, then)
} else { } else {
AirTree::no_op().hoist_over(then) AirTree::no_op(then)
} }
} }
Pattern::List { elements, tail, .. } => { Pattern::List { elements, tail, .. } => {
@ -1067,8 +1065,8 @@ impl<'a> CodeGenerator<'a> {
elems.reverse(); elems.reverse();
let list_access = if elements.is_empty() { if elements.is_empty() {
AirTree::list_empty(value, props.msg_func) AirTree::list_empty(value, props.msg_func, then)
} else { } else {
AirTree::list_access( AirTree::list_access(
elems, elems,
@ -1081,10 +1079,9 @@ impl<'a> CodeGenerator<'a> {
} else { } else {
ExpectLevel::Items ExpectLevel::Items
}, },
then,
) )
}; }
list_access.hoist_over(then)
} }
Pattern::Constructor { Pattern::Constructor {
arguments, arguments,
@ -1095,7 +1092,7 @@ impl<'a> CodeGenerator<'a> {
if tipo.is_bool() { if tipo.is_bool() {
assert!(props.kind.is_expect()); assert!(props.kind.is_expect());
AirTree::assert_bool(name == "True", value, props.msg_func).hoist_over(then) AirTree::assert_bool(name == "True", value, props.msg_func, then)
} else if tipo.is_void() { } else if tipo.is_void() {
AirTree::let_assignment("_", value, then) AirTree::let_assignment("_", value, then)
} else { } else {
@ -1201,7 +1198,7 @@ impl<'a> CodeGenerator<'a> {
} else { } else {
(false, None) (false, None)
}; };
AirTree::fields_expose(fields, local_value, msg, is_expect).hoist_over(then) AirTree::fields_expose(fields, local_value, msg, is_expect, then)
}; };
// TODO: See if we can combine these two if-conditions; // TODO: See if we can combine these two if-conditions;
@ -1223,13 +1220,12 @@ impl<'a> CodeGenerator<'a> {
panic!("Found constructor type {} with 0 constructors", name) panic!("Found constructor type {} with 0 constructors", name)
}); });
let assert_constr = AirTree::assert_constr_index( AirTree::assert_constr_index(
index, index,
AirTree::local_var(&constructor_name, tipo.clone()), AirTree::local_var(&constructor_name, tipo.clone()),
props.msg_func, props.msg_func,
); then,
)
assert_constr.hoist_over(then)
} else { } else {
then then
} }
@ -1314,10 +1310,8 @@ impl<'a> CodeGenerator<'a> {
}; };
// This `value` is either value param that was passed in or local var // This `value` is either value param that was passed in or local var
let tuple_access =
AirTree::tuple_access(fields, tipo.clone(), value, msg, is_expect);
tuple_access.hoist_over(then) AirTree::tuple_access(fields, tipo.clone(), value, msg, is_expect, then)
} }
} }
} }
@ -1349,17 +1343,9 @@ impl<'a> CodeGenerator<'a> {
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);
let tuple_access = AirTree::tuple_access(
vec![fst_name.clone(), snd_name.clone()],
inner_list_type.clone(),
AirTree::local_var(&pair_name, inner_list_type.clone()),
msg_func.clone(),
msg_func.is_some(),
);
let expect_fst = self.expect_type_assign( let expect_fst = self.expect_type_assign(
&inner_pair_types[0], &inner_pair_types[0],
AirTree::local_var(fst_name, inner_pair_types[0].clone()), AirTree::local_var(fst_name.clone(), inner_pair_types[0].clone()),
defined_data_types, defined_data_types,
location, location,
msg_func.clone(), msg_func.clone(),
@ -1367,14 +1353,20 @@ impl<'a> CodeGenerator<'a> {
let expect_snd = self.expect_type_assign( let expect_snd = self.expect_type_assign(
&inner_pair_types[1], &inner_pair_types[1],
AirTree::local_var(snd_name, inner_pair_types[1].clone()), AirTree::local_var(snd_name.clone(), inner_pair_types[1].clone()),
defined_data_types, defined_data_types,
location, location,
msg_func.clone(), msg_func.clone(),
); );
let anon_func_body = let anon_func_body = AirTree::tuple_access(
tuple_access.hoist_over(AirTree::let_assignment("_", expect_fst, expect_snd)); vec![fst_name, snd_name],
inner_list_type.clone(),
AirTree::local_var(&pair_name, inner_list_type.clone()),
msg_func.clone(),
msg_func.is_some(),
AirTree::let_assignment("_", expect_fst, expect_snd),
);
let unwrap_function = AirTree::anon_func(vec![pair_name], anon_func_body); let unwrap_function = AirTree::anon_func(vec![pair_name], anon_func_body);
@ -1499,17 +1491,9 @@ impl<'a> CodeGenerator<'a> {
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);
let tuple_access = AirTree::tuple_access(
vec![fst_name.clone(), snd_name.clone()],
tipo.clone(),
AirTree::local_var(&pair_name, tipo.clone()),
msg_func.clone(),
msg_func.is_some(),
);
let expect_fst = self.expect_type_assign( let expect_fst = self.expect_type_assign(
&tuple_inner_types[0], &tuple_inner_types[0],
AirTree::local_var(fst_name, tuple_inner_types[0].clone()), AirTree::local_var(fst_name.clone(), tuple_inner_types[0].clone()),
defined_data_types, defined_data_types,
location, location,
msg_func.clone(), msg_func.clone(),
@ -1517,17 +1501,22 @@ impl<'a> CodeGenerator<'a> {
let expect_snd = self.expect_type_assign( let expect_snd = self.expect_type_assign(
&tuple_inner_types[1], &tuple_inner_types[1],
AirTree::local_var(snd_name, tuple_inner_types[1].clone()), AirTree::local_var(snd_name.clone(), tuple_inner_types[1].clone()),
defined_data_types, defined_data_types,
location, location,
msg_func, msg_func.clone(),
); );
AirTree::let_assignment( let tuple_access = AirTree::tuple_access(
&pair_name, vec![fst_name, snd_name],
value, tipo.clone(),
tuple_access.hoist_over(AirTree::let_assignment("_", expect_fst, expect_snd)), AirTree::local_var(&pair_name, tipo.clone()),
) msg_func.clone(),
msg_func.is_some(),
AirTree::let_assignment("_", expect_fst, expect_snd),
);
AirTree::let_assignment(&pair_name, value, tuple_access)
} else if tipo.is_tuple() { } else if tipo.is_tuple() {
let tuple_inner_types = tipo.get_inner_types(); let tuple_inner_types = tipo.get_inner_types();
@ -1567,10 +1556,9 @@ impl<'a> CodeGenerator<'a> {
AirTree::local_var(&tuple_name, tipo.clone()), AirTree::local_var(&tuple_name, tipo.clone()),
msg_func, msg_func,
true, true,
then,
); );
let tuple_access = tuple_access.hoist_over(then);
AirTree::let_assignment(&tuple_name, value, tuple_access) AirTree::let_assignment(&tuple_name, value, tuple_access)
// Constructor // Constructor
@ -1653,7 +1641,7 @@ impl<'a> CodeGenerator<'a> {
); );
constr_args.reverse(); constr_args.reverse();
let assign = if constr_args.is_empty() { let then = if constr_args.is_empty() {
AirTree::fields_empty( AirTree::fields_empty(
AirTree::local_var( AirTree::local_var(
format!( format!(
@ -1663,6 +1651,7 @@ impl<'a> CodeGenerator<'a> {
tipo.clone(), tipo.clone(),
), ),
msg_term.clone(), msg_term.clone(),
constr_then,
) )
} else { } else {
AirTree::fields_expose( AirTree::fields_expose(
@ -1676,11 +1665,10 @@ impl<'a> CodeGenerator<'a> {
), ),
msg_term.clone(), msg_term.clone(),
true, true,
constr_then,
) )
}; };
let then = assign.hoist_over(constr_then);
AirTree::clause( AirTree::clause(
format!("__subject_span_{}_{}", location.start, location.end), format!("__subject_span_{}_{}", location.start, location.end),
AirTree::int(index), AirTree::int(index),
@ -1796,8 +1784,12 @@ impl<'a> CodeGenerator<'a> {
clause_then = AirTree::let_assignment( clause_then = AirTree::let_assignment(
&clause_guard_name, &clause_guard_name,
builder::handle_clause_guard(guard), builder::handle_clause_guard(guard),
AirTree::clause_guard(&clause_guard_name, AirTree::bool(true), bool()) AirTree::clause_guard(
.hoist_over(clause_then), &clause_guard_name,
AirTree::bool(true),
bool(),
clause_then,
),
); );
} }
@ -2279,6 +2271,7 @@ impl<'a> CodeGenerator<'a> {
// Since check_last_item is false this will never get added to the final uplc anyway // Since check_last_item is false this will never get added to the final uplc anyway
None, None,
ExpectLevel::None, ExpectLevel::None,
elems_then,
) )
} else { } else {
assert!(defined_tails.len() >= elems.len()); assert!(defined_tails.len() >= elems.len());
@ -2292,10 +2285,11 @@ impl<'a> CodeGenerator<'a> {
.collect_vec(), .collect_vec(),
list_tail, list_tail,
subject_tipo.clone(), subject_tipo.clone(),
elems_then,
) )
}; };
(AirTree::void(), list_assign.hoist_over(elems_then)) (AirTree::void(), list_assign)
} }
Pattern::Constructor { Pattern::Constructor {
name, name,
@ -2422,8 +2416,8 @@ impl<'a> CodeGenerator<'a> {
), ),
None, None,
false, false,
next_then,
) )
.hoist_over(next_then)
}; };
(AirTree::int(constr_index), field_assign) (AirTree::int(constr_index), field_assign)
@ -2530,7 +2524,7 @@ impl<'a> CodeGenerator<'a> {
_ => unreachable!(), _ => unreachable!(),
} }
let tuple_name_assigns = if props.final_clause && !names_to_define.is_empty() { if props.final_clause && !names_to_define.is_empty() {
names_to_define.sort_by(|(id1, _), (id2, _)| id1.cmp(id2)); names_to_define.sort_by(|(id1, _), (id2, _)| id1.cmp(id2));
let names = let names =
@ -2544,19 +2538,20 @@ impl<'a> CodeGenerator<'a> {
names names
}); });
AirTree::tuple_access( (
names, AirTree::void(),
subject_tipo.clone(), AirTree::tuple_access(
AirTree::local_var(&props.original_subject_name, subject_tipo.clone()), names,
None, subject_tipo.clone(),
false, AirTree::local_var(&props.original_subject_name, subject_tipo.clone()),
None,
false,
tuple_name_assigns,
),
) )
.hoist_over(tuple_name_assigns)
} else { } else {
tuple_name_assigns (AirTree::void(), tuple_name_assigns)
}; }
(AirTree::void(), tuple_name_assigns)
} }
} }
} }
@ -2580,8 +2575,12 @@ impl<'a> CodeGenerator<'a> {
match pattern { match pattern {
Pattern::Int { value, .. } => { Pattern::Int { value, .. } => {
props.complex_clause = true; props.complex_clause = true;
AirTree::clause_guard(&props.original_subject_name, AirTree::int(value), int()) AirTree::clause_guard(
.hoist_over(then) &props.original_subject_name,
AirTree::int(value),
int(),
then,
)
} }
Pattern::Var { name, .. } => AirTree::let_assignment( Pattern::Var { name, .. } => AirTree::let_assignment(
name, name,
@ -2609,11 +2608,9 @@ impl<'a> CodeGenerator<'a> {
subject_tipo.clone(), subject_tipo.clone(),
false, false,
None, None,
then,
) )
.hoist_over(then)
} else { } else {
let mut clause_assigns = vec![];
let ClauseProperties { let ClauseProperties {
specific_clause: specific_clause:
SpecificClause::ListClause { SpecificClause::ListClause {
@ -2630,54 +2627,66 @@ impl<'a> CodeGenerator<'a> {
defined_tails.push(props.original_subject_name.clone()); defined_tails.push(props.original_subject_name.clone());
for (index, _) in elements.iter().enumerate() { for (index, _) in elements.iter().enumerate() {
let prev_tail_name = if index == 0 {
props.original_subject_name.clone()
} else {
format!("{}_{}", tail_name_base, index - 1)
};
let tail_name = format!("{tail_name_base}_{index}"); let tail_name = format!("{tail_name_base}_{index}");
if elements.len() - 1 == index { if elements.len() - 1 == index {
if tail.is_some() { if tail.is_none() {
clause_assigns.push(AirTree::list_clause_guard(
prev_tail_name,
subject_tipo.clone(),
true,
None,
));
} else {
clause_assigns.push(AirTree::list_clause_guard(
prev_tail_name,
subject_tipo.clone(),
true,
Some(tail_name.to_string()),
));
clause_assigns.push(AirTree::list_clause_guard(
tail_name.to_string(),
subject_tipo.clone(),
false,
None,
));
*current_index += 1; *current_index += 1;
defined_tails.push(tail_name); defined_tails.push(tail_name);
} }
} else { } else {
clause_assigns.push(AirTree::list_clause_guard(
prev_tail_name,
subject_tipo.clone(),
true,
Some(tail_name.to_string()),
));
*current_index += 1; *current_index += 1;
defined_tails.push(tail_name); defined_tails.push(tail_name);
}; };
} }
let (_, assigns) = self.clause_pattern(pattern, subject_tipo, props, then); let (_, assigns) = self.clause_pattern(pattern, subject_tipo, props, then);
AirTree::UnhoistedSequence(clause_assigns).hoist_over(assigns)
elements
.iter()
.enumerate()
.rfold(assigns, |then, (index, _)| {
let prev_tail_name = if index == 0 {
props.original_subject_name.clone()
} else {
format!("{}_{}", tail_name_base, index - 1)
};
let tail_name = format!("{tail_name_base}_{index}");
if elements.len() - 1 == index {
if tail.is_some() {
AirTree::list_clause_guard(
prev_tail_name,
subject_tipo.clone(),
true,
None,
then,
)
} else {
AirTree::list_clause_guard(
prev_tail_name,
subject_tipo.clone(),
true,
Some(tail_name.to_string()),
AirTree::list_clause_guard(
tail_name.to_string(),
subject_tipo.clone(),
false,
None,
then,
),
)
}
} else {
AirTree::list_clause_guard(
prev_tail_name,
subject_tipo.clone(),
true,
Some(tail_name.to_string()),
then,
)
}
})
} }
} }
Pattern::Constructor { Pattern::Constructor {
@ -2689,8 +2698,8 @@ impl<'a> CodeGenerator<'a> {
&props.original_subject_name, &props.original_subject_name,
AirTree::bool(constr_name == "True"), AirTree::bool(constr_name == "True"),
bool(), bool(),
then,
) )
.hoist_over(then)
} else { } else {
let (cond, assign) = let (cond, assign) =
self.clause_pattern(pattern, subject_tipo, props, then); self.clause_pattern(pattern, subject_tipo, props, then);
@ -2706,8 +2715,8 @@ impl<'a> CodeGenerator<'a> {
&props.original_subject_name, &props.original_subject_name,
cond, cond,
subject_tipo.clone(), subject_tipo.clone(),
assign,
) )
.hoist_over(assign)
} }
} }
} }
@ -2721,13 +2730,12 @@ impl<'a> CodeGenerator<'a> {
_ => unreachable!(), _ => unreachable!(),
}; };
let tuple_access = AirTree::tuple_clause_guard( AirTree::tuple_clause_guard(
&props.original_subject_name, &props.original_subject_name,
subject_tipo.clone(), subject_tipo.clone(),
defined_indices, defined_indices,
); assign,
)
tuple_access.hoist_over(assign)
} }
} }
} }
@ -3215,7 +3223,9 @@ impl<'a> CodeGenerator<'a> {
func_params.clone() func_params.clone()
}; };
body = AirTree::define_func( let node_to_edit = air_tree.find_air_tree_node(tree_path);
let defined_function = AirTree::define_func(
&key.function_name, &key.function_name,
&key.module_name, &key.module_name,
variant, variant,
@ -3223,36 +3233,34 @@ impl<'a> CodeGenerator<'a> {
is_recursive, is_recursive,
recursive_nonstatics, recursive_nonstatics,
body, body,
node_to_edit.clone(),
); );
let function_deps = self.hoist_dependent_functions( let defined_dependencies = self.hoist_dependent_functions(
deps, deps,
params_empty, params_empty,
key, (key, variant),
variant,
hoisted_functions, hoisted_functions,
functions_to_hoist, functions_to_hoist,
defined_function,
); );
let node_to_edit = air_tree.find_air_tree_node(tree_path);
// now hoist full function onto validator tree // now hoist full function onto validator tree
*node_to_edit = function_deps.hoist_over(body.hoist_over(node_to_edit.clone())); *node_to_edit = defined_dependencies;
hoisted_functions.push((key.clone(), variant.clone())); hoisted_functions.push((key.clone(), variant.clone()));
} else { } else {
body = self let defined_func = self.hoist_dependent_functions(
.hoist_dependent_functions( deps,
deps, params_empty,
params_empty, (key, variant),
key, hoisted_functions,
variant, functions_to_hoist,
hoisted_functions, body,
functions_to_hoist, );
)
.hoist_over(body);
self.zero_arg_functions self.zero_arg_functions
.insert((key.clone(), variant.clone()), body.to_vec()); .insert((key.clone(), variant.clone()), defined_func.to_vec());
} }
} }
HoistableFunction::CyclicFunction { HoistableFunction::CyclicFunction {
@ -3269,27 +3277,28 @@ impl<'a> CodeGenerator<'a> {
modify_cyclic_calls(body, key, &self.cyclic_functions); modify_cyclic_calls(body, key, &self.cyclic_functions);
} }
let cyclic_body = AirTree::define_cyclic_func( let node_to_edit = air_tree.find_air_tree_node(tree_path);
let cyclic_func = AirTree::define_cyclic_func(
&key.function_name, &key.function_name,
&key.module_name, &key.module_name,
variant, variant,
functions, functions,
node_to_edit.clone(),
); );
let function_deps = self.hoist_dependent_functions( let defined_dependencies = self.hoist_dependent_functions(
deps, deps,
// cyclic functions always have params // cyclic functions always have params
false, false,
key, (key, variant),
variant,
hoisted_functions, hoisted_functions,
functions_to_hoist, functions_to_hoist,
cyclic_func,
); );
let node_to_edit = air_tree.find_air_tree_node(tree_path);
// now hoist full function onto validator tree // now hoist full function onto validator tree
*node_to_edit = *node_to_edit = defined_dependencies;
function_deps.hoist_over(cyclic_body.hoist_over(node_to_edit.clone()));
hoisted_functions.push((key.clone(), variant.clone())); hoisted_functions.push((key.clone(), variant.clone()));
} }
@ -3306,21 +3315,20 @@ impl<'a> CodeGenerator<'a> {
&mut self, &mut self,
deps: (&TreePath, Vec<(FunctionAccessKey, String)>), deps: (&TreePath, Vec<(FunctionAccessKey, String)>),
params_empty: bool, params_empty: bool,
key: &FunctionAccessKey, func_key_variant: (&FunctionAccessKey, &Variant),
variant: &String,
hoisted_functions: &mut Vec<(FunctionAccessKey, String)>, hoisted_functions: &mut Vec<(FunctionAccessKey, String)>,
functions_to_hoist: &IndexMap< functions_to_hoist: &IndexMap<
FunctionAccessKey, FunctionAccessKey,
IndexMap<String, (TreePath, HoistableFunction)>, IndexMap<String, (TreePath, HoistableFunction)>,
>, >,
air_tree: AirTree,
) -> AirTree { ) -> AirTree {
let (key, variant) = func_key_variant;
let (func_path, func_deps) = deps; let (func_path, func_deps) = deps;
let mut deps_vec = func_deps; let mut deps_vec = func_deps;
let mut sorted_dep_vec = vec![]; let mut sorted_dep_vec = vec![];
let mut dep_insertions = vec![];
while let Some(dep) = deps_vec.pop() { while let Some(dep) = deps_vec.pop() {
let function_variants = functions_to_hoist let function_variants = functions_to_hoist
.get(&dep.0) .get(&dep.0)
@ -3369,98 +3377,100 @@ impl<'a> CodeGenerator<'a> {
} }
sorted_dep_vec.dedup(); sorted_dep_vec.dedup();
sorted_dep_vec.reverse();
// This part handles hoisting dependencies sorted_dep_vec
while let Some((dep_key, dep_variant)) = sorted_dep_vec.pop() { .into_iter()
if (!params_empty .fold(air_tree, |then, (dep_key, dep_variant)| {
// if the dependency is the same as the function we're hoisting if (!params_empty
// or we hoisted it, then skip it // if the dependency is the same as the function we're hoisting
&& hoisted_functions.iter().any(|(generic, variant)| { // or we hoisted it, then skip it
generic == &dep_key && variant == &dep_variant && hoisted_functions.iter().any(|(generic, variant)| {
})) generic == &dep_key && variant == &dep_variant
|| (&dep_key == key && &dep_variant == variant) }))
{ || (&dep_key == key && &dep_variant == variant)
continue; {
} return then;
let dependency = functions_to_hoist
.get(&dep_key)
.unwrap_or_else(|| panic!("Missing Function Definition"));
let (dep_path, dep_function) = dependency
.get(&dep_variant)
.unwrap_or_else(|| panic!("Missing Function Variant Definition"));
// In the case of zero args, we need to hoist the dependency function to the top of the zero arg function
if &dep_path.common_ancestor(func_path) == func_path || params_empty {
match dep_function.clone() {
HoistableFunction::Function {
body: mut dep_air_tree,
deps: dependency_deps,
params: dependent_params,
} => {
if dependent_params.is_empty() {
// continue for zero arg functions. They are treated like global hoists.
continue;
}
let is_dependent_recursive = dependency_deps
.iter()
.any(|(key, variant)| &dep_key == key && &dep_variant == variant);
let recursive_nonstatics = if is_dependent_recursive {
modify_self_calls(
&mut dep_air_tree,
&dep_key,
&dep_variant,
&dependent_params,
)
} else {
dependent_params.clone()
};
dep_insertions.push(AirTree::define_func(
&dep_key.function_name,
&dep_key.module_name,
&dep_variant,
dependent_params,
is_dependent_recursive,
recursive_nonstatics,
dep_air_tree,
));
if !params_empty {
hoisted_functions.push((dep_key.clone(), dep_variant.clone()));
}
}
HoistableFunction::CyclicFunction { functions, .. } => {
let mut functions = functions.clone();
for (_, body) in functions.iter_mut() {
modify_cyclic_calls(body, &dep_key, &self.cyclic_functions);
}
dep_insertions.push(AirTree::define_cyclic_func(
&dep_key.function_name,
&dep_key.module_name,
&dep_variant,
functions,
));
if !params_empty {
hoisted_functions.push((dep_key.clone(), dep_variant.clone()));
}
}
HoistableFunction::Link(_) => unreachable!(),
HoistableFunction::CyclicLink(_) => unreachable!(),
} }
}
}
dep_insertions.reverse(); let dependency = functions_to_hoist
.get(&dep_key)
.unwrap_or_else(|| panic!("Missing Function Definition"));
AirTree::UnhoistedSequence(dep_insertions) let (dep_path, dep_function) = dependency
.get(&dep_variant)
.unwrap_or_else(|| panic!("Missing Function Variant Definition"));
// In the case of zero args, we need to hoist the dependency function to the top of the zero arg function
// The dependency we are hoisting should have an equal path to the function we hoisted
// if we are going to hoist it
if &dep_path.common_ancestor(func_path) == func_path || params_empty {
match dep_function.clone() {
HoistableFunction::Function {
body: mut dep_air_tree,
deps: dependency_deps,
params: dependent_params,
} => {
if dependent_params.is_empty() {
// continue for zero arg functions. They are treated like global hoists.
return then;
}
let is_dependent_recursive = dependency_deps
.iter()
.any(|(key, variant)| &dep_key == key && &dep_variant == variant);
let recursive_nonstatics = if is_dependent_recursive {
modify_self_calls(
&mut dep_air_tree,
&dep_key,
&dep_variant,
&dependent_params,
)
} else {
dependent_params.clone()
};
if !params_empty {
hoisted_functions.push((dep_key.clone(), dep_variant.clone()));
}
AirTree::define_func(
&dep_key.function_name,
&dep_key.module_name,
&dep_variant,
dependent_params,
is_dependent_recursive,
recursive_nonstatics,
dep_air_tree,
then,
)
}
HoistableFunction::CyclicFunction { functions, .. } => {
let mut functions = functions.clone();
for (_, body) in functions.iter_mut() {
modify_cyclic_calls(body, &dep_key, &self.cyclic_functions);
}
if !params_empty {
hoisted_functions.push((dep_key.clone(), dep_variant.clone()));
}
AirTree::define_cyclic_func(
&dep_key.function_name,
&dep_key.module_name,
&dep_variant,
functions,
then,
)
}
HoistableFunction::Link(_) => unreachable!(),
HoistableFunction::CyclicLink(_) => unreachable!(),
}
} else {
then
}
})
} }
fn define_dependent_functions( fn define_dependent_functions(
@ -3520,11 +3530,11 @@ impl<'a> CodeGenerator<'a> {
current_depth, current_depth,
depth_index, depth_index,
&mut |air_tree, tree_path| { &mut |air_tree, tree_path| {
if let AirTree::Expression(AirExpression::Var { if let AirTree::Var {
constructor, constructor,
variant_name, variant_name,
.. ..
}) = air_tree } = air_tree
{ {
let ValueConstructorVariant::ModuleFn { let ValueConstructorVariant::ModuleFn {
name: func_name, name: func_name,

View File

@ -432,6 +432,8 @@ impl AirTree {
args, args,
} }
} }
#[allow(clippy::too_many_arguments)]
pub fn define_func( pub fn define_func(
func_name: impl ToString, func_name: impl ToString,
module_name: impl ToString, module_name: impl ToString,
@ -1160,9 +1162,7 @@ impl AirTree {
AirTree::ByteArray { bytes } => air_vec.push(Air::ByteArray { AirTree::ByteArray { bytes } => air_vec.push(Air::ByteArray {
bytes: bytes.clone(), bytes: bytes.clone(),
}), }),
AirTree::CurvePoint { point } => air_vec.push(Air::CurvePoint { AirTree::CurvePoint { point } => air_vec.push(Air::CurvePoint { point: *point }),
point: point.clone(),
}),
AirTree::Bool { value } => air_vec.push(Air::Bool { value: *value }), AirTree::Bool { value } => air_vec.push(Air::Bool { value: *value }),
AirTree::List { tipo, tail, items } => { AirTree::List { tipo, tail, items } => {
air_vec.push(Air::List { air_vec.push(Air::List {
@ -1212,7 +1212,7 @@ impl AirTree {
AirTree::Builtin { func, tipo, args } => { AirTree::Builtin { func, tipo, args } => {
air_vec.push(Air::Builtin { air_vec.push(Air::Builtin {
count: args.len(), count: args.len(),
func: func.clone(), func: *func,
tipo: tipo.clone(), tipo: tipo.clone(),
}); });
@ -1613,15 +1613,7 @@ impl AirTree {
apply_with_func_last, apply_with_func_last,
), ),
AirTree::TupleClause { AirTree::TupleClause { otherwise, .. } => {
subject_tipo,
indices,
predefined_indices,
subject_name,
complex_clause,
then,
otherwise,
} => {
tuple_then_index = Some(index_count.next_number()); tuple_then_index = Some(index_count.next_number());
otherwise.do_traverse_tree_with( otherwise.do_traverse_tree_with(
tree_path, tree_path,
@ -1670,9 +1662,7 @@ impl AirTree {
apply_with_func_last, apply_with_func_last,
); );
} }
AirTree::TupleClause { AirTree::TupleClause { then, .. } => {
then, otherwise, ..
} => {
let Some(index) = tuple_then_index else { let Some(index) = tuple_then_index else {
unreachable!() unreachable!()
}; };