checkpoint;
Remaining work is on function hoisting. Functions have been defined and monomorphized
This commit is contained in:
parent
ae9de11e77
commit
62660e04b5
|
@ -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> {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue