From 62660e04b5fefedbdde0bebed85f00495077f265 Mon Sep 17 00:00:00 2001 From: microproofs Date: Fri, 21 Jul 2023 01:14:22 -0400 Subject: [PATCH] checkpoint; Remaining work is on function hoisting. Functions have been defined and monomorphized --- crates/aiken-lang/src/gen_uplc2.rs | 202 ++++++++++++--------- crates/aiken-lang/src/gen_uplc2/builder.rs | 8 +- crates/aiken-lang/src/gen_uplc2/tree.rs | 16 +- 3 files changed, 129 insertions(+), 97 deletions(-) diff --git a/crates/aiken-lang/src/gen_uplc2.rs b/crates/aiken-lang/src/gen_uplc2.rs index 2ecf7b97..3e965ace 100644 --- a/crates/aiken-lang/src/gen_uplc2.rs +++ b/crates/aiken-lang/src/gen_uplc2.rs @@ -2214,17 +2214,18 @@ impl<'a> CodeGenerator<'a> { &mut air_tree, &mut functions_to_hoist, &mut used_functions, + &mut TreePath::new(), + 0, + 0, ); - println!("FUNCTIONS TO HOIST {:#?}", functions_to_hoist); - while let Some((key, variant_name)) = used_functions.pop() { defined_functions.push((key.clone(), variant_name.clone())); let function_variants = functions_to_hoist .get(&key) .unwrap_or_else(|| panic!("Missing Function Definition")); - let (_, function) = function_variants + let (tree_path, function) = function_variants .get(&variant_name) .unwrap_or_else(|| panic!("Missing Function Variant Definition")); @@ -2232,12 +2233,15 @@ impl<'a> CodeGenerator<'a> { let mut hoist_body = body.clone(); let mut hoist_deps = deps.clone(); - self.hoist_functions( + let mut tree_path = tree_path.clone(); + + self.define_dependent_functions( &mut hoist_body, &mut functions_to_hoist, &mut used_functions, &defined_functions, &mut hoist_deps, + &mut tree_path, ); let function_variants = functions_to_hoist @@ -2258,10 +2262,14 @@ impl<'a> CodeGenerator<'a> { println!("FUNCTIONS DEFINED {:#?}", defined_functions); println!("FUNCTIONS USED {:#?}", used_functions); + // First we need to sort functions by dependencies + + // Now we need to hoist the functions to the top of the validator + air_tree } - fn hoist_functions( + fn define_dependent_functions( &mut self, air_tree: &mut AirTree, function_usage: &mut IndexMap< @@ -2271,8 +2279,21 @@ impl<'a> CodeGenerator<'a> { used_functions: &mut Vec<(FunctionAccessKey, String)>, defined_functions: &[(FunctionAccessKey, String)], current_function_deps: &mut Vec<(FunctionAccessKey, String)>, + validator_tree_path: &mut TreePath, ) { - self.find_function_vars_and_depth(air_tree, function_usage, current_function_deps); + let Some((depth, index)) = validator_tree_path.pop() + else { return }; + + validator_tree_path.push(depth, index); + + self.find_function_vars_and_depth( + air_tree, + function_usage, + current_function_deps, + validator_tree_path, + depth + 1, + 0, + ); for (generic_function_key, variant_name) in current_function_deps.iter() { if !used_functions @@ -2295,80 +2316,101 @@ impl<'a> CodeGenerator<'a> { IndexMap, >, dependency_functions: &mut Vec<(FunctionAccessKey, String)>, + path: &mut TreePath, + current_depth: usize, + depth_index: usize, ) { - air_tree.traverse_tree_with(&mut |air_tree, tree_path| { - if let AirTree::Expression(AirExpression::Var { constructor, .. }) = air_tree { - let ValueConstructorVariant::ModuleFn { - name: func_name, - module, - builtin: None, - .. - } = &constructor.variant - else { return }; + air_tree.traverse_tree_with_path( + path, + current_depth, + depth_index, + &mut |air_tree, tree_path| { + if let AirTree::Expression(AirExpression::Var { constructor, .. }) = air_tree { + let ValueConstructorVariant::ModuleFn { + name: func_name, + module, + builtin: None, + .. + } = &constructor.variant + else { return }; - let function_var_tipo = &constructor.tipo; - println!("FUNCTION VAR TYPE {:#?}", function_var_tipo); + let function_var_tipo = &constructor.tipo; - let generic_function_key = FunctionAccessKey { - module_name: module.clone(), - function_name: func_name.clone(), - }; + let generic_function_key = FunctionAccessKey { + module_name: module.clone(), + function_name: func_name.clone(), + }; - let function_def = self - .functions - .get(&generic_function_key) - .unwrap_or_else(|| panic!("Missing Function Definition")); + let function_def = self + .functions + .get(&generic_function_key) + .unwrap_or_else(|| panic!("Missing Function Definition")); - println!("Function Def {:#?}", function_def); + let mut function_var_types = function_var_tipo + .arg_types() + .unwrap_or_else(|| panic!("Expected a function tipo with arg types")); - let mut function_var_types = function_var_tipo - .arg_types() - .unwrap_or_else(|| panic!("Expected a function tipo with arg types")); + function_var_types.push( + function_var_tipo + .return_type() + .unwrap_or_else(|| panic!("Should have return type")), + ); - function_var_types.push( - function_var_tipo - .return_type() - .unwrap_or_else(|| panic!("Should have return type")), - ); + let mut function_def_types = function_def + .arguments + .iter() + .map(|arg| &arg.tipo) + .collect_vec(); - let mut function_def_types = function_def - .arguments - .iter() - .map(|arg| &arg.tipo) - .collect_vec(); + function_def_types.push(&function_def.return_type); - function_def_types.push(&function_def.return_type); + let mono_types: IndexMap> = if !function_def_types.is_empty() { + function_def_types + .into_iter() + .zip(function_var_types.into_iter()) + .flat_map(|(func_tipo, var_tipo)| { + get_generic_id_and_type(func_tipo, &var_tipo) + }) + .collect() + } else { + IndexMap::new() + }; - let mono_types: IndexMap> = if !function_def_types.is_empty() { - function_def_types - .into_iter() - .zip(function_var_types.into_iter()) - .flat_map(|(func_tipo, var_tipo)| { - get_generic_id_and_type(func_tipo, &var_tipo) - }) - .collect() - } else { - IndexMap::new() - }; + let variant_name = mono_types + .iter() + .sorted_by(|(id, _), (id2, _)| id.cmp(id2)) + .map(|(_, tipo)| get_variant_name(tipo)) + .join(""); - println!("MONO TYPES {:#?}", mono_types); + if !dependency_functions + .iter() + .any(|(key, name)| key == &generic_function_key && name == &variant_name) + { + dependency_functions + .push((generic_function_key.clone(), variant_name.clone())); + } - let variant_name = mono_types - .iter() - .sorted_by(|(id, _), (id2, _)| id.cmp(id2)) - .map(|(_, tipo)| get_variant_name(tipo)) - .join(""); + if let Some(func_variants) = function_usage.get_mut(&generic_function_key) { + if let Some((path, _)) = func_variants.get_mut(&variant_name) { + *path = path.common_ancestor(tree_path); + } else { + let mut function_air_tree_body = self.build(&function_def.body); - if !dependency_functions - .iter() - .any(|(key, name)| key == &generic_function_key && name == &variant_name) - { - dependency_functions.push((generic_function_key.clone(), variant_name.clone())); - } + monomorphize(&mut function_air_tree_body, &mono_types); - if let Some(func_variants) = function_usage.get_mut(&generic_function_key) { - if let Some((path, _)) = func_variants.get_mut(&variant_name) { - *path = path.common_ancestor(tree_path); + erase_opaque_type_operations( + &mut function_air_tree_body, + &self.data_types, + ); + + func_variants.insert( + variant_name, + ( + tree_path.current_path(), + UserFunction::Function(function_air_tree_body, vec![]), + ), + ); + } } else { let mut function_air_tree_body = self.build(&function_def.body); @@ -2376,35 +2418,21 @@ impl<'a> CodeGenerator<'a> { erase_opaque_type_operations(&mut function_air_tree_body, &self.data_types); - func_variants.insert( + let mut function_variant_path = IndexMap::new(); + + function_variant_path.insert( variant_name, ( tree_path.current_path(), UserFunction::Function(function_air_tree_body, vec![]), ), ); + + function_usage.insert(generic_function_key, function_variant_path); } - } else { - let mut function_air_tree_body = self.build(&function_def.body); - - monomorphize(&mut function_air_tree_body, &mono_types); - - erase_opaque_type_operations(&mut function_air_tree_body, &self.data_types); - - let mut function_variant_path = IndexMap::new(); - - function_variant_path.insert( - variant_name, - ( - tree_path.current_path(), - UserFunction::Function(function_air_tree_body, vec![]), - ), - ); - - function_usage.insert(generic_function_key, function_variant_path); } - } - }); + }, + ); } fn uplc_code_gen(&mut self, ir_stack: &mut Vec) -> Term { diff --git a/crates/aiken-lang/src/gen_uplc2/builder.rs b/crates/aiken-lang/src/gen_uplc2/builder.rs index 2ca283cd..bc17d03d 100644 --- a/crates/aiken-lang/src/gen_uplc2/builder.rs +++ b/crates/aiken-lang/src/gen_uplc2/builder.rs @@ -175,8 +175,6 @@ pub fn find_and_replace_generics( new_args.push(arg); } - println!("SO ARGS ARE {:#?}", new_args); - let ret = find_and_replace_generics(ret, mono_types); let t = Type::Fn { @@ -199,10 +197,7 @@ pub fn find_and_replace_generics( let var_type = var_tipo.as_ref().borrow().clone(); match var_type { - TypeVar::Link { tipo } => { - find_and_replace_generics(&tipo, mono_types); - tipo - } + TypeVar::Link { tipo } => find_and_replace_generics(&tipo, mono_types), TypeVar::Generic { .. } | TypeVar::Unbound { .. } => unreachable!(), } } @@ -328,7 +323,6 @@ pub fn get_variant_name(t: &Arc) -> String { pub fn monomorphize(air_tree: &mut AirTree, mono_types: &IndexMap>) { air_tree.traverse_tree_with(&mut |air_tree: &mut AirTree, _| { let mut held_types = air_tree.mut_held_types(); - println!("Held types: {:#?}", held_types); while let Some(tipo) = held_types.pop() { *tipo = find_and_replace_generics(tipo, mono_types) diff --git a/crates/aiken-lang/src/gen_uplc2/tree.rs b/crates/aiken-lang/src/gen_uplc2/tree.rs index ce63ce05..dd25ec67 100644 --- a/crates/aiken-lang/src/gen_uplc2/tree.rs +++ b/crates/aiken-lang/src/gen_uplc2/tree.rs @@ -1,5 +1,5 @@ use indexmap::IndexSet; -use std::{borrow::BorrowMut, slice::Iter, sync::Arc}; +use std::{borrow::BorrowMut, path, slice::Iter, sync::Arc}; use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction}; use crate::{ @@ -24,8 +24,8 @@ impl TreePath { self.path.push((depth, index)); } - pub fn pop(&mut self) { - self.path.pop(); + pub fn pop(&mut self) -> Option<(usize, usize)> { + self.path.pop() } pub fn current_path(&self) -> Self { @@ -1333,6 +1333,16 @@ impl AirTree { self.do_traverse_tree_with(&mut tree_path, 0, 0, with); } + pub fn traverse_tree_with_path( + &mut self, + path: &mut TreePath, + current_depth: usize, + depth_index: usize, + with: &mut impl FnMut(&mut AirTree, &TreePath), + ) { + self.do_traverse_tree_with(path, current_depth, depth_index, with); + } + fn do_traverse_tree_with( &mut self, tree_path: &mut TreePath,