diff --git a/crates/aiken-lang/src/gen_uplc2.rs b/crates/aiken-lang/src/gen_uplc2.rs index 73ed0057..08a0fd53 100644 --- a/crates/aiken-lang/src/gen_uplc2.rs +++ b/crates/aiken-lang/src/gen_uplc2.rs @@ -2235,6 +2235,7 @@ impl<'a> CodeGenerator<'a> { let mut functions_to_hoist = IndexMap::new(); let mut used_functions = vec![]; let mut defined_functions = vec![]; + let mut hoisted_functions = vec![]; erase_opaque_type_operations(&mut air_tree, &self.data_types); @@ -2286,10 +2287,6 @@ impl<'a> CodeGenerator<'a> { } } - println!("FUNCTIONS TO HOIST {:#?}", functions_to_hoist); - println!("FUNCTIONS DEFINED {:#?}", defined_functions); - println!("FUNCTIONS USED {:#?}", used_functions); - // First we need to sort functions by dependencies // here's also where we deal with mutual recursion let mut function_vec = vec![]; @@ -2300,8 +2297,6 @@ impl<'a> CodeGenerator<'a> { } } - println!("FUNCTION VEC {:#?}", function_vec); - function_vec.reverse(); while let Some((generic_func, variant)) = function_vec.pop() { @@ -2341,6 +2336,13 @@ impl<'a> CodeGenerator<'a> { // Now we need to hoist the functions to the top of the validator for (key, variant) in sorted_function_vec { + if hoisted_functions + .iter() + .any(|(func_key, func_variant)| func_key == key && func_variant == variant) + { + continue; + } + let function_variants = functions_to_hoist .get(key) .unwrap_or_else(|| panic!("Missing Function Definition")); @@ -2349,7 +2351,14 @@ impl<'a> CodeGenerator<'a> { .get(variant) .unwrap_or_else(|| panic!("Missing Function Variant Definition")); - self.hoist_function(&mut air_tree, tree_path, function, key, variant); + self.hoist_function( + &mut air_tree, + tree_path, + function, + key, + variant, + &mut hoisted_functions, + ); } println!("NOW AIR TREE {:#?}", air_tree); @@ -2363,6 +2372,7 @@ impl<'a> CodeGenerator<'a> { function: &UserFunction, key: &FunctionAccessKey, variant: &String, + hoisted_functions: &mut Vec<(FunctionAccessKey, String)>, ) { if let UserFunction::Function(body, deps) = function { let node_to_edit = air_tree.find_air_tree_node(tree_path); @@ -2390,6 +2400,10 @@ impl<'a> CodeGenerator<'a> { }) .collect_vec(); + for dependency in deps { + todo!() + } + // now hoist full function onto validator tree *node_to_edit = AirTree::define_func( &key.function_name, @@ -2400,6 +2414,8 @@ impl<'a> CodeGenerator<'a> { body.clone(), ) .hoist_over(node_to_edit.clone()); + + hoisted_functions.push((key.clone(), variant.clone())); } else { todo!() } diff --git a/crates/aiken-lang/src/gen_uplc2/tree.rs b/crates/aiken-lang/src/gen_uplc2/tree.rs index 91a4f32d..45befb42 100644 --- a/crates/aiken-lang/src/gen_uplc2/tree.rs +++ b/crates/aiken-lang/src/gen_uplc2/tree.rs @@ -1,4 +1,5 @@ use indexmap::IndexSet; +use itertools::Itertools; use std::{borrow::BorrowMut, slice::Iter, sync::Arc}; use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction}; @@ -53,6 +54,30 @@ impl TreePath { common_ancestor } + + pub fn diff_paths(&self, other: &Self) -> Self { + let mut self_iter = self.path.iter(); + let mut other_iter = other.path.iter(); + + let mut self_next = self_iter.next(); + let mut other_next = other_iter.next(); + + while self_next.is_some() && other_next.is_some() { + let self_next_level = self_next.unwrap(); + let other_next_level = other_next.unwrap(); + + if self_next_level == other_next_level { + self_next = self_iter.next(); + other_next = other_iter.next(); + } else { + unreachable!() + } + } + + TreePath { + path: self_iter.cloned().collect_vec(), + } + } } impl Default for TreePath { @@ -1751,7 +1776,14 @@ impl AirTree { &'a mut self, tree_path_iter: &mut Iter<(usize, usize)>, ) -> &'a mut AirTree { - if let Some((_depth, index)) = tree_path_iter.next() { + // For Finding the air node we skip over the define func ops since those are added later on. + if let AirTree::Statement { + statement: AirStatement::DefineFunc { .. }, + hoisted_over: Some(hoisted_over), + } = self + { + hoisted_over.as_mut().do_find_air_tree_node(tree_path_iter) + } else if let Some((_depth, index)) = tree_path_iter.next() { let mut children_nodes = vec![]; match self { AirTree::Statement { @@ -1767,15 +1799,6 @@ impl AirTree { panic!("Tree Path index outside tree children nodes") } } - AirStatement::DefineFunc { func_body, .. } => { - if *index == 0 { - func_body.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - hoisted_over.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } AirStatement::AssertConstr { constr, .. } => { if *index == 0 { constr.as_mut().do_find_air_tree_node(tree_path_iter) @@ -1858,6 +1881,7 @@ impl AirTree { panic!("Tree Path index outside tree children nodes") } } + AirStatement::DefineFunc { .. } => unreachable!(), }, AirTree::Expression(e) => match e { AirExpression::List { items, .. }