checkpoint;

Remaining work is on function hoisting. Functions have been defined and monomorphized
This commit is contained in:
microproofs 2023-07-21 01:14:22 -04:00 committed by Kasey
parent ae9de11e77
commit 62660e04b5
3 changed files with 129 additions and 97 deletions

View File

@ -2214,17 +2214,18 @@ impl<'a> CodeGenerator<'a> {
&mut air_tree, &mut air_tree,
&mut functions_to_hoist, &mut functions_to_hoist,
&mut used_functions, &mut used_functions,
&mut TreePath::new(),
0,
0,
); );
println!("FUNCTIONS TO HOIST {:#?}", functions_to_hoist);
while let Some((key, variant_name)) = used_functions.pop() { while let Some((key, variant_name)) = used_functions.pop() {
defined_functions.push((key.clone(), variant_name.clone())); defined_functions.push((key.clone(), variant_name.clone()));
let function_variants = functions_to_hoist let function_variants = functions_to_hoist
.get(&key) .get(&key)
.unwrap_or_else(|| panic!("Missing Function Definition")); .unwrap_or_else(|| panic!("Missing Function Definition"));
let (_, function) = function_variants let (tree_path, function) = function_variants
.get(&variant_name) .get(&variant_name)
.unwrap_or_else(|| panic!("Missing Function Variant Definition")); .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_body = body.clone();
let mut hoist_deps = deps.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 hoist_body,
&mut functions_to_hoist, &mut functions_to_hoist,
&mut used_functions, &mut used_functions,
&defined_functions, &defined_functions,
&mut hoist_deps, &mut hoist_deps,
&mut tree_path,
); );
let function_variants = functions_to_hoist let function_variants = functions_to_hoist
@ -2258,10 +2262,14 @@ impl<'a> CodeGenerator<'a> {
println!("FUNCTIONS DEFINED {:#?}", defined_functions); println!("FUNCTIONS DEFINED {:#?}", defined_functions);
println!("FUNCTIONS USED {:#?}", used_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 air_tree
} }
fn hoist_functions( fn define_dependent_functions(
&mut self, &mut self,
air_tree: &mut AirTree, air_tree: &mut AirTree,
function_usage: &mut IndexMap< function_usage: &mut IndexMap<
@ -2271,8 +2279,21 @@ impl<'a> CodeGenerator<'a> {
used_functions: &mut Vec<(FunctionAccessKey, String)>, used_functions: &mut Vec<(FunctionAccessKey, String)>,
defined_functions: &[(FunctionAccessKey, String)], defined_functions: &[(FunctionAccessKey, String)],
current_function_deps: &mut Vec<(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() { for (generic_function_key, variant_name) in current_function_deps.iter() {
if !used_functions if !used_functions
@ -2295,80 +2316,101 @@ impl<'a> CodeGenerator<'a> {
IndexMap<String, (TreePath, UserFunction)>, IndexMap<String, (TreePath, UserFunction)>,
>, >,
dependency_functions: &mut Vec<(FunctionAccessKey, String)>, 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| { air_tree.traverse_tree_with_path(
if let AirTree::Expression(AirExpression::Var { constructor, .. }) = air_tree { path,
let ValueConstructorVariant::ModuleFn { current_depth,
name: func_name, depth_index,
module, &mut |air_tree, tree_path| {
builtin: None, if let AirTree::Expression(AirExpression::Var { constructor, .. }) = air_tree {
.. let ValueConstructorVariant::ModuleFn {
} = &constructor.variant name: func_name,
else { return }; module,
builtin: None,
..
} = &constructor.variant
else { return };
let function_var_tipo = &constructor.tipo; let function_var_tipo = &constructor.tipo;
println!("FUNCTION VAR TYPE {:#?}", function_var_tipo);
let generic_function_key = FunctionAccessKey { let generic_function_key = FunctionAccessKey {
module_name: module.clone(), module_name: module.clone(),
function_name: func_name.clone(), function_name: func_name.clone(),
}; };
let function_def = self let function_def = self
.functions .functions
.get(&generic_function_key) .get(&generic_function_key)
.unwrap_or_else(|| panic!("Missing Function Definition")); .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 function_var_types.push(
.arg_types() function_var_tipo
.unwrap_or_else(|| panic!("Expected a function tipo with arg types")); .return_type()
.unwrap_or_else(|| panic!("Should have return type")),
);
function_var_types.push( let mut function_def_types = function_def
function_var_tipo .arguments
.return_type() .iter()
.unwrap_or_else(|| panic!("Should have return type")), .map(|arg| &arg.tipo)
); .collect_vec();
let mut function_def_types = function_def function_def_types.push(&function_def.return_type);
.arguments
.iter()
.map(|arg| &arg.tipo)
.collect_vec();
function_def_types.push(&function_def.return_type); let mono_types: IndexMap<u64, Arc<Type>> = 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<u64, Arc<Type>> = if !function_def_types.is_empty() { let variant_name = mono_types
function_def_types .iter()
.into_iter() .sorted_by(|(id, _), (id2, _)| id.cmp(id2))
.zip(function_var_types.into_iter()) .map(|(_, tipo)| get_variant_name(tipo))
.flat_map(|(func_tipo, var_tipo)| { .join("");
get_generic_id_and_type(func_tipo, &var_tipo)
})
.collect()
} else {
IndexMap::new()
};
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 if let Some(func_variants) = function_usage.get_mut(&generic_function_key) {
.iter() if let Some((path, _)) = func_variants.get_mut(&variant_name) {
.sorted_by(|(id, _), (id2, _)| id.cmp(id2)) *path = path.common_ancestor(tree_path);
.map(|(_, tipo)| get_variant_name(tipo)) } else {
.join(""); let mut function_air_tree_body = self.build(&function_def.body);
if !dependency_functions monomorphize(&mut function_air_tree_body, &mono_types);
.iter()
.any(|(key, name)| key == &generic_function_key && name == &variant_name)
{
dependency_functions.push((generic_function_key.clone(), variant_name.clone()));
}
if let Some(func_variants) = function_usage.get_mut(&generic_function_key) { erase_opaque_type_operations(
if let Some((path, _)) = func_variants.get_mut(&variant_name) { &mut function_air_tree_body,
*path = path.common_ancestor(tree_path); &self.data_types,
);
func_variants.insert(
variant_name,
(
tree_path.current_path(),
UserFunction::Function(function_air_tree_body, vec![]),
),
);
}
} else { } else {
let mut function_air_tree_body = self.build(&function_def.body); 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); 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, variant_name,
( (
tree_path.current_path(), tree_path.current_path(),
UserFunction::Function(function_air_tree_body, vec![]), 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<Air>) -> Term<Name> { fn uplc_code_gen(&mut self, ir_stack: &mut Vec<Air>) -> Term<Name> {

View File

@ -175,8 +175,6 @@ pub fn find_and_replace_generics(
new_args.push(arg); new_args.push(arg);
} }
println!("SO ARGS ARE {:#?}", new_args);
let ret = find_and_replace_generics(ret, mono_types); let ret = find_and_replace_generics(ret, mono_types);
let t = Type::Fn { let t = Type::Fn {
@ -199,10 +197,7 @@ pub fn find_and_replace_generics(
let var_type = var_tipo.as_ref().borrow().clone(); let var_type = var_tipo.as_ref().borrow().clone();
match var_type { match var_type {
TypeVar::Link { tipo } => { TypeVar::Link { tipo } => find_and_replace_generics(&tipo, mono_types),
find_and_replace_generics(&tipo, mono_types);
tipo
}
TypeVar::Generic { .. } | TypeVar::Unbound { .. } => unreachable!(), TypeVar::Generic { .. } | TypeVar::Unbound { .. } => unreachable!(),
} }
} }
@ -328,7 +323,6 @@ pub fn get_variant_name(t: &Arc<Type>) -> String {
pub fn monomorphize(air_tree: &mut AirTree, mono_types: &IndexMap<u64, Arc<Type>>) { pub fn monomorphize(air_tree: &mut AirTree, mono_types: &IndexMap<u64, Arc<Type>>) {
air_tree.traverse_tree_with(&mut |air_tree: &mut AirTree, _| { air_tree.traverse_tree_with(&mut |air_tree: &mut AirTree, _| {
let mut held_types = air_tree.mut_held_types(); let mut held_types = air_tree.mut_held_types();
println!("Held types: {:#?}", held_types);
while let Some(tipo) = held_types.pop() { while let Some(tipo) = held_types.pop() {
*tipo = find_and_replace_generics(tipo, mono_types) *tipo = find_and_replace_generics(tipo, mono_types)

View File

@ -1,5 +1,5 @@
use indexmap::IndexSet; 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 uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction};
use crate::{ use crate::{
@ -24,8 +24,8 @@ impl TreePath {
self.path.push((depth, index)); self.path.push((depth, index));
} }
pub fn pop(&mut self) { pub fn pop(&mut self) -> Option<(usize, usize)> {
self.path.pop(); self.path.pop()
} }
pub fn current_path(&self) -> Self { pub fn current_path(&self) -> Self {
@ -1333,6 +1333,16 @@ impl AirTree {
self.do_traverse_tree_with(&mut tree_path, 0, 0, with); 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( fn do_traverse_tree_with(
&mut self, &mut self,
tree_path: &mut TreePath, tree_path: &mut TreePath,