a checkpoint for function hoisting start and type fix

This commit is contained in:
microproofs 2023-07-13 15:28:38 -04:00 committed by Kasey
parent 55ae708e3e
commit 9704cafefe
6 changed files with 1022 additions and 108 deletions

View File

@ -671,7 +671,6 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
FunctionAccessKey { FunctionAccessKey {
module_name: "".to_string(), module_name: "".to_string(),
function_name: "not".to_string(), function_name: "not".to_string(),
variant_name: "".to_string(),
}, },
Function { Function {
arguments: vec![Arg { arguments: vec![Arg {
@ -722,7 +721,6 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
FunctionAccessKey { FunctionAccessKey {
module_name: "".to_string(), module_name: "".to_string(),
function_name: "identity".to_string(), function_name: "identity".to_string(),
variant_name: "".to_string(),
}, },
Function { Function {
arguments: vec![Arg { arguments: vec![Arg {
@ -769,7 +767,6 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
FunctionAccessKey { FunctionAccessKey {
module_name: "".to_string(), module_name: "".to_string(),
function_name: "always".to_string(), function_name: "always".to_string(),
variant_name: "".to_string(),
}, },
Function { Function {
can_error: false, can_error: false,
@ -832,7 +829,6 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
FunctionAccessKey { FunctionAccessKey {
module_name: "".to_string(), module_name: "".to_string(),
function_name: "flip".to_string(), function_name: "flip".to_string(),
variant_name: "".to_string(),
}, },
Function { Function {
can_error: false, can_error: false,

View File

@ -702,7 +702,6 @@ impl<'a> CodeGenerator<'a> {
let func = self.functions.get(&FunctionAccessKey { let func = self.functions.get(&FunctionAccessKey {
module_name: module_name.clone(), module_name: module_name.clone(),
function_name: name.clone(), function_name: name.clone(),
variant_name: String::new(),
}); });
let type_info = self.module_types.get(module_name).unwrap(); let type_info = self.module_types.get(module_name).unwrap();
@ -3068,7 +3067,7 @@ impl<'a> CodeGenerator<'a> {
func_stack.define_func( func_stack.define_func(
function_access_key.function_name.clone(), function_access_key.function_name.clone(),
function_access_key.module_name.clone(), function_access_key.module_name.clone(),
function_access_key.variant_name.clone(), "",
func_comp.args.clone(), func_comp.args.clone(),
func_comp.recursive, func_comp.recursive,
recursion_stack, recursion_stack,
@ -3112,7 +3111,7 @@ impl<'a> CodeGenerator<'a> {
let mut skip = false; let mut skip = false;
for ir in function_ir.clone() { for ir in function_ir.clone() {
let Air::Var { constructor, variant_name, .. } = ir let Air::Var { constructor, .. } = ir
else { else {
continue; continue;
}; };
@ -3125,7 +3124,6 @@ impl<'a> CodeGenerator<'a> {
let ir_function_key = FunctionAccessKey { let ir_function_key = FunctionAccessKey {
module_name: module.clone(), module_name: module.clone(),
function_name: func_name.clone(), function_name: func_name.clone(),
variant_name: variant_name.clone(),
}; };
if recursion_func_map.contains_key(&ir_function_key) && func == &ir_function_key { if recursion_func_map.contains_key(&ir_function_key) && func == &ir_function_key {
@ -3203,7 +3201,6 @@ impl<'a> CodeGenerator<'a> {
let non_variant_function_key = FunctionAccessKey { let non_variant_function_key = FunctionAccessKey {
module_name: module.clone(), module_name: module.clone(),
function_name: name.clone(), function_name: name.clone(),
variant_name: String::new(),
}; };
if let Some(function) = self.functions.get(&non_variant_function_key).cloned() { if let Some(function) = self.functions.get(&non_variant_function_key).cloned() {
@ -3243,7 +3240,6 @@ impl<'a> CodeGenerator<'a> {
let function_key = FunctionAccessKey { let function_key = FunctionAccessKey {
module_name: module.clone(), module_name: module.clone(),
function_name: non_variant_function_key.function_name, function_name: non_variant_function_key.function_name,
variant_name: variant_name.clone(),
}; };
ir_stack[index] = Air::Var { ir_stack[index] = Air::Var {
@ -3278,13 +3274,11 @@ impl<'a> CodeGenerator<'a> {
let current_func = FunctionAccessKey { let current_func = FunctionAccessKey {
module_name: module.clone(), module_name: module.clone(),
function_name: func_name.clone(), function_name: func_name.clone(),
variant_name: String::new(),
}; };
let current_func_as_variant = FunctionAccessKey { let current_func_as_variant = FunctionAccessKey {
module_name: module.clone(), module_name: module.clone(),
function_name: func_name.clone(), function_name: func_name.clone(),
variant_name: variant_name.clone(),
}; };
let function = self.functions.get(&current_func); let function = self.functions.get(&current_func);
@ -3335,7 +3329,6 @@ impl<'a> CodeGenerator<'a> {
FunctionAccessKey { FunctionAccessKey {
module_name: current_func.module_name, module_name: current_func.module_name,
function_name: current_func.function_name, function_name: current_func.function_name,
variant_name,
}, },
(), (),
); );
@ -3394,7 +3387,6 @@ impl<'a> CodeGenerator<'a> {
let function_key = FunctionAccessKey { let function_key = FunctionAccessKey {
module_name: "".to_string(), module_name: "".to_string(),
function_name: name.to_string(), function_name: name.to_string(),
variant_name: "".to_string(),
}; };
let function_stack = AirStack { let function_stack = AirStack {
@ -3416,7 +3408,6 @@ impl<'a> CodeGenerator<'a> {
.map(|item| FunctionAccessKey { .map(|item| FunctionAccessKey {
module_name: "".to_string(), module_name: "".to_string(),
function_name: item, function_name: item,
variant_name: "".to_string(),
}) })
.collect_vec(), .collect_vec(),
recursive: false, recursive: false,
@ -4178,14 +4169,12 @@ impl<'a> CodeGenerator<'a> {
FunctionAccessKey { FunctionAccessKey {
module_name, module_name,
function_name, function_name,
variant_name,
}, },
ir, ir,
) in zero_arg_functions.into_iter() ) in zero_arg_functions.into_iter()
{ {
let name_module = let name_module = format!("{module_name}_{function_name}");
format!("{module_name}_{function_name}{variant_name}"); let name = function_name.to_string();
let name = format!("{function_name}{variant_name}");
if text == &name || text == &name_module { if text == &name || text == &name_module {
let mut term = self.uplc_code_gen(&mut ir.clone()); let mut term = self.uplc_code_gen(&mut ir.clone());
term = term term = term

View File

@ -53,7 +53,6 @@ pub type ConstrUsageKey = String;
pub struct FunctionAccessKey { pub struct FunctionAccessKey {
pub module_name: String, pub module_name: String,
pub function_name: String, pub function_name: String,
pub variant_name: String,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -766,7 +765,6 @@ pub fn match_ir_for_recursion(
let var_func_access = FunctionAccessKey { let var_func_access = FunctionAccessKey {
module_name: module, module_name: module,
function_name: func_name.clone(), function_name: func_name.clone(),
variant_name: variant_name.clone(),
}; };
if function_access_key.clone() == var_func_access { if function_access_key.clone() == var_func_access {
@ -1571,7 +1569,7 @@ pub fn handle_func_dependencies(
temp_stack.define_func( temp_stack.define_func(
dependency.function_name.clone(), dependency.function_name.clone(),
dependency.module_name.clone(), dependency.module_name.clone(),
dependency.variant_name.clone(), "",
depend_comp.args.clone(), depend_comp.args.clone(),
depend_comp.recursive, depend_comp.recursive,
recursion_stack, recursion_stack,
@ -1607,7 +1605,6 @@ pub fn handle_recursion_ir(
&FunctionAccessKey { &FunctionAccessKey {
function_name: func_key.function_name.clone(), function_name: func_key.function_name.clone(),
module_name: func_key.module_name.clone(), module_name: func_key.module_name.clone(),
variant_name: func_key.variant_name.clone(),
}, },
index, index,
); );

View File

@ -25,14 +25,20 @@ use crate::{
FunctionAccessKey, SpecificClause, FunctionAccessKey, SpecificClause,
}, },
}, },
gen_uplc2::builder::{convert_opaque_type, find_and_replace_generics, get_generic_id_and_type}, gen_uplc2::builder::{
convert_opaque_type, erase_opaque_operations, find_and_replace_generics,
get_generic_id_and_type,
},
tipo::{ tipo::{
ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor, ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
ValueConstructorVariant, ValueConstructorVariant,
}, },
}; };
use self::tree::{AirExpression, AirTree}; use self::{
builder::{IndexCounter, TreePath},
tree::{AirExpression, AirStatement, AirTree},
};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum CodeGenFunction { pub enum CodeGenFunction {
@ -40,6 +46,12 @@ pub enum CodeGenFunction {
Link(String), Link(String),
} }
#[derive(Clone, Debug)]
pub enum UserFunction {
Function(AirTree, Term<Name>),
Link(String),
}
#[derive(Clone)] #[derive(Clone)]
pub struct CodeGenerator<'a> { pub struct CodeGenerator<'a> {
defined_functions: IndexMap<FunctionAccessKey, ()>, defined_functions: IndexMap<FunctionAccessKey, ()>,
@ -94,7 +106,7 @@ impl<'a> CodeGenerator<'a> {
println!("{:#?}", validator_args_tree); println!("{:#?}", validator_args_tree);
println!("{:#?}", validator_args_tree.to_vec()); println!("{:#?}", validator_args_tree.to_vec());
let hydrated_tree = self.hoist_functions(validator_args_tree); let full_tree = self.hoist_functions(validator_args_tree);
todo!() todo!()
} }
@ -106,6 +118,8 @@ impl<'a> CodeGenerator<'a> {
println!("{:#?}", air_tree); println!("{:#?}", air_tree);
println!("{:#?}", air_tree.to_vec()); println!("{:#?}", air_tree.to_vec());
let full_tree = self.hoist_functions(air_tree);
todo!() todo!()
} }
@ -222,7 +236,6 @@ impl<'a> CodeGenerator<'a> {
} }
TypedExpr::ModuleSelect { TypedExpr::ModuleSelect {
tipo,
module_name, module_name,
constructor: ModuleValueConstructor::Fn { name, .. }, constructor: ModuleValueConstructor::Fn { name, .. },
.. ..
@ -273,8 +286,12 @@ impl<'a> CodeGenerator<'a> {
} }
}, },
TypedExpr::BinOp { TypedExpr::BinOp {
name, left, right, .. name,
} => AirTree::binop(*name, left.tipo(), self.build(left), self.build(right)), left,
right,
tipo,
..
} => AirTree::binop(*name, tipo.clone(), self.build(left), self.build(right)),
TypedExpr::Assignment { TypedExpr::Assignment {
tipo, tipo,
@ -360,6 +377,7 @@ impl<'a> CodeGenerator<'a> {
&clauses, &clauses,
last_clause, last_clause,
&subject.tipo(), &subject.tipo(),
tipo,
&mut ClauseProperties::init( &mut ClauseProperties::init(
&subject.tipo(), &subject.tipo(),
constr_var.clone(), constr_var.clone(),
@ -370,8 +388,8 @@ impl<'a> CodeGenerator<'a> {
let constr_assign = AirTree::let_assignment(&constr_var, self.build(subject)); let constr_assign = AirTree::let_assignment(&constr_var, self.build(subject));
let when_assign = AirTree::when( let when_assign = AirTree::when(
subject_name, subject_name,
subject.tipo(), tipo.clone(),
AirTree::local_var(constr_var, tipo.clone()), AirTree::local_var(constr_var, subject.tipo()),
clauses, clauses,
); );
@ -438,7 +456,6 @@ impl<'a> CodeGenerator<'a> {
let func = self.functions.get(&FunctionAccessKey { let func = self.functions.get(&FunctionAccessKey {
module_name: module_name.clone(), module_name: module_name.clone(),
function_name: name.clone(), function_name: name.clone(),
variant_name: String::new(),
}); });
let type_info = self.module_types.get(module_name).unwrap(); let type_info = self.module_types.get(module_name).unwrap();
@ -549,7 +566,7 @@ impl<'a> CodeGenerator<'a> {
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
if props.full_check { if props.full_check {
let mut index_map = IndexMap::new(); let mut index_map = IndexMap::new();
let tipo = convert_opaque_type(tipo, &self.data_types); let non_opaque_tipo = convert_opaque_type(tipo, &self.data_types);
let assignment = AirTree::let_assignment(name, value); let assignment = AirTree::let_assignment(name, value);
let val = AirTree::local_var(name, tipo.clone()); let val = AirTree::local_var(name, tipo.clone());
@ -558,7 +575,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::let_assignment(name, assignment.hoist_over(val)) AirTree::let_assignment(name, assignment.hoist_over(val))
} else { } else {
let expect = self.expect_type_assign( let expect = self.expect_type_assign(
&tipo, &non_opaque_tipo,
val.clone(), val.clone(),
&mut index_map, &mut index_map,
pattern.location(), pattern.location(),
@ -1159,7 +1176,7 @@ impl<'a> CodeGenerator<'a> {
.flat_map(|item| get_generic_id_and_type(item.0, &item.1)) .flat_map(|item| get_generic_id_and_type(item.0, &item.1))
.collect() .collect()
} else { } else {
vec![].into_iter().collect() IndexMap::new()
}; };
let data_type_name = format!("__expect_{}_{}", data_type.name, data_type_variant); let data_type_name = format!("__expect_{}_{}", data_type.name, data_type_variant);
@ -1339,6 +1356,7 @@ impl<'a> CodeGenerator<'a> {
clauses: &[TypedClause], clauses: &[TypedClause],
final_clause: TypedClause, final_clause: TypedClause,
subject_tipo: &Arc<Type>, subject_tipo: &Arc<Type>,
return_tipo: &Arc<Type>,
props: &mut ClauseProperties, props: &mut ClauseProperties,
) -> AirTree { ) -> AirTree {
assert!( assert!(
@ -1396,6 +1414,7 @@ impl<'a> CodeGenerator<'a> {
rest_clauses, rest_clauses,
final_clause, final_clause,
subject_tipo, subject_tipo,
return_tipo,
&mut next_clause_props, &mut next_clause_props,
), ),
complex_clause, complex_clause,
@ -1407,6 +1426,7 @@ impl<'a> CodeGenerator<'a> {
rest_clauses, rest_clauses,
final_clause, final_clause,
subject_tipo, subject_tipo,
return_tipo,
&mut next_clause_props, &mut next_clause_props,
), ),
) )
@ -1421,6 +1441,7 @@ impl<'a> CodeGenerator<'a> {
rest_clauses, rest_clauses,
final_clause, final_clause,
subject_tipo, subject_tipo,
return_tipo,
&mut next_clause_props, &mut next_clause_props,
), ),
complex_clause, complex_clause,
@ -1456,6 +1477,7 @@ impl<'a> CodeGenerator<'a> {
rest_clauses, rest_clauses,
final_clause, final_clause,
subject_tipo, subject_tipo,
return_tipo,
&mut next_clause_props, &mut next_clause_props,
), ),
); );
@ -1532,6 +1554,7 @@ impl<'a> CodeGenerator<'a> {
rest_clauses, rest_clauses,
final_clause, final_clause,
subject_tipo, subject_tipo,
return_tipo,
&mut next_clause_props, &mut next_clause_props,
), ),
) )
@ -1544,6 +1567,7 @@ impl<'a> CodeGenerator<'a> {
rest_clauses, rest_clauses,
final_clause, final_clause,
subject_tipo, subject_tipo,
return_tipo,
&mut next_clause_props, &mut next_clause_props,
), ),
next_tail_name, next_tail_name,
@ -1587,6 +1611,7 @@ impl<'a> CodeGenerator<'a> {
rest_clauses, rest_clauses,
final_clause, final_clause,
subject_tipo, subject_tipo,
return_tipo,
&mut next_clause_props, &mut next_clause_props,
), ),
) )
@ -1601,6 +1626,7 @@ impl<'a> CodeGenerator<'a> {
rest_clauses, rest_clauses,
final_clause, final_clause,
subject_tipo, subject_tipo,
return_tipo,
&mut next_clause_props, &mut next_clause_props,
), ),
props.complex_clause, props.complex_clause,
@ -2194,14 +2220,18 @@ impl<'a> CodeGenerator<'a> {
AirTree::anon_func(arg_names, arg_assigns.hoist_over(body)) AirTree::anon_func(arg_names, arg_assigns.hoist_over(body))
} }
fn hoist_functions(&mut self, mut validator_args_tree: AirTree) -> AirTree { fn hoist_functions(&mut self, mut air_tree: AirTree) -> AirTree {
let mut functions_to_hoist = IndexMap::new(); let mut functions_to_hoist = IndexMap::new();
let mut function_holder = IndexMap::new(); let mut function_holder = IndexMap::new();
erase_opaque_operations(&mut air_tree, &self.data_types);
self.find_function_vars_and_depth( self.find_function_vars_and_depth(
&mut validator_args_tree, &air_tree,
&mut functions_to_hoist, &mut functions_to_hoist,
&mut function_holder, &mut function_holder,
&mut TreePath::new(),
0,
0, 0,
); );
@ -2210,17 +2240,141 @@ impl<'a> CodeGenerator<'a> {
fn find_function_vars_and_depth( fn find_function_vars_and_depth(
&mut self, &mut self,
validator_args_tree: &mut AirTree, validator_args_tree: &AirTree,
function_usage: &mut IndexMap<FunctionAccessKey, usize>, function_usage: &mut IndexMap<FunctionAccessKey, IndexMap<String, TreePath>>,
function_holder: &mut IndexMap<FunctionAccessKey, AirTree>, function_holder: &mut IndexMap<FunctionAccessKey, IndexMap<String, UserFunction>>,
tree_path: &mut TreePath,
current_depth: usize, current_depth: usize,
depth_index: usize,
) { ) {
let mut index_count = IndexCounter::new();
tree_path.push(current_depth, depth_index);
match validator_args_tree { match validator_args_tree {
AirTree::Statement { AirTree::Statement {
statement, statement,
hoisted_over: Some(hoisted_over), hoisted_over: Some(hoisted_over),
} => todo!(), } => {
match statement {
AirStatement::Let { value, .. } => {
self.find_function_vars_and_depth(
value,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirStatement::DefineFunc { func_body, .. } => {
self.find_function_vars_and_depth(
func_body,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirStatement::AssertConstr { constr, .. } => {
self.find_function_vars_and_depth(
constr,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirStatement::AssertBool { value, .. } => {
self.find_function_vars_and_depth(
value,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirStatement::ClauseGuard { pattern, .. } => {
self.find_function_vars_and_depth(
pattern,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirStatement::ListClauseGuard { .. } => {}
AirStatement::TupleGuard { .. } => {}
AirStatement::FieldsExpose { record, .. } => {
self.find_function_vars_and_depth(
record,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirStatement::ListAccessor { list, .. } => {
self.find_function_vars_and_depth(
list,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirStatement::ListExpose { .. } => {}
AirStatement::TupleAccessor { tuple, .. } => {
self.find_function_vars_and_depth(
tuple,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirStatement::NoOp => {}
};
self.find_function_vars_and_depth(
hoisted_over,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirTree::Expression(e) => match e { AirTree::Expression(e) => match e {
AirExpression::List { items, .. } => {
for item in items {
self.find_function_vars_and_depth(
item,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
}
AirExpression::Tuple { items, .. } => {
for item in items {
self.find_function_vars_and_depth(
item,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
}
AirExpression::Var { AirExpression::Var {
constructor, constructor,
name, name,
@ -2235,10 +2389,48 @@ impl<'a> CodeGenerator<'a> {
else { return }; 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(),
variant_name: "".to_string(), };
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"));
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();
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()
}; };
todo!() todo!()
@ -2248,7 +2440,9 @@ impl<'a> CodeGenerator<'a> {
func, func,
function_usage, function_usage,
function_holder, function_holder,
tree_path,
current_depth + 1, current_depth + 1,
index_count.next(),
); );
for arg in args { for arg in args {
@ -2256,86 +2450,345 @@ impl<'a> CodeGenerator<'a> {
arg, arg,
function_usage, function_usage,
function_holder, function_holder,
tree_path,
current_depth + 1, current_depth + 1,
index_count.next(),
); );
} }
} }
AirExpression::Fn { params, func_body } => todo!(), AirExpression::Fn { func_body, .. } => {
AirExpression::Builtin { func, tipo, args } => todo!(), self.find_function_vars_and_depth(
AirExpression::BinOp { func_body,
name, function_usage,
tipo, function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::Builtin { args, .. } => {
for arg in args {
self.find_function_vars_and_depth(
arg,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
}
AirExpression::BinOp { left, right, .. } => {
self.find_function_vars_and_depth(
left, left,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
right, right,
} => todo!(), function_usage,
AirExpression::UnOp { op, arg } => todo!(), function_holder,
AirExpression::UnWrapData { tipo, value } => todo!(), tree_path,
AirExpression::WrapData { tipo, value } => todo!(), current_depth + 1,
index_count.next(),
);
}
AirExpression::UnOp { arg, .. } => {
self.find_function_vars_and_depth(
arg,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::UnWrapData { value, .. } => {
self.find_function_vars_and_depth(
value,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::WrapData { value, .. } => {
self.find_function_vars_and_depth(
value,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::When { AirExpression::When {
tipo, subject, clauses, ..
subject_name, } => {
self.find_function_vars_and_depth(
subject, subject,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
clauses, clauses,
} => todo!(), function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::Clause { AirExpression::Clause {
tipo,
subject_name,
complex_clause,
pattern, pattern,
then, then,
otherwise, otherwise,
} => todo!(), ..
} => {
self.find_function_vars_and_depth(
pattern,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
then,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
otherwise,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::ListClause { AirExpression::ListClause {
tipo, then, otherwise, ..
tail_name, } => {
next_tail_name, self.find_function_vars_and_depth(
complex_clause,
then, then,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
otherwise, otherwise,
} => todo!(), function_usage,
AirExpression::WrapClause { then, otherwise } => todo!(), function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::WrapClause { then, otherwise } => {
self.find_function_vars_and_depth(
then,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
otherwise,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::TupleClause { AirExpression::TupleClause {
tipo, then, otherwise, ..
indices, } => {
predefined_indices, self.find_function_vars_and_depth(
subject_name,
type_count,
complex_clause,
then, then,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
otherwise, otherwise,
} => todo!(), function_usage,
AirExpression::Finally { pattern, then } => todo!(), function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::Finally { pattern, then } => {
self.find_function_vars_and_depth(
pattern,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
then,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::If { AirExpression::If {
tipo,
pattern, pattern,
then, then,
otherwise, otherwise,
} => todo!(), ..
AirExpression::Constr { tag, tipo, args } => todo!(), } => {
AirExpression::RecordUpdate { self.find_function_vars_and_depth(
highest_index, pattern,
indices, function_usage,
tipo, function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
then,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
otherwise,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::Constr { args, .. } => {
for arg in args {
self.find_function_vars_and_depth(
arg,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
}
AirExpression::RecordUpdate { record, args, .. } => {
self.find_function_vars_and_depth(
record, record,
args, function_usage,
} => todo!(), function_holder,
AirExpression::RecordAccess { tree_path,
field_index, current_depth + 1,
tipo, index_count.next(),
);
for arg in args {
self.find_function_vars_and_depth(
arg,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
}
AirExpression::RecordAccess { record, .. } => {
self.find_function_vars_and_depth(
record, record,
} => todo!(), function_usage,
AirExpression::TupleIndex { function_holder,
tipo, tree_path,
tuple_index, current_depth + 1,
index_count.next(),
);
}
AirExpression::TupleIndex { tuple, .. } => {
self.find_function_vars_and_depth(
tuple, tuple,
} => todo!(), function_usage,
AirExpression::ErrorTerm { tipo } => todo!(), function_holder,
AirExpression::Trace { tipo, msg, then } => todo!(), tree_path,
AirExpression::FieldsEmpty { constr } => todo!(), current_depth + 1,
AirExpression::ListEmpty { list } => todo!(), index_count.next(),
);
}
AirExpression::Trace { msg, then, .. } => {
self.find_function_vars_and_depth(
msg,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
self.find_function_vars_and_depth(
then,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::FieldsEmpty { constr } => {
self.find_function_vars_and_depth(
constr,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
AirExpression::ListEmpty { list } => {
self.find_function_vars_and_depth(
list,
function_usage,
function_holder,
tree_path,
current_depth + 1,
index_count.next(),
);
}
_ => {} _ => {}
}, },
_ => unreachable!(), _ => unreachable!(),
} }
tree_path.pop();
} }
} }

View File

@ -3,8 +3,8 @@ use indexmap::IndexMap;
use crate::{ use crate::{
ast::TypedDataType, ast::TypedDataType,
builtins::bool, builtins::bool,
gen_uplc::builder::{lookup_data_type_by_tipo, DataTypeKey}, gen_uplc::builder::{lookup_data_type_by_tipo, DataTypeKey, FunctionAccessKey},
tipo::TypeVar, tipo::{TypeVar, ValueConstructorVariant},
}; };
use std::sync::Arc; use std::sync::Arc;
@ -13,7 +13,42 @@ use crate::{
tipo::Type, tipo::Type,
}; };
use super::tree::AirTree; use super::tree::{AirExpression, AirStatement, AirTree};
#[derive(Clone, Debug)]
pub struct TreePath {
path: Vec<(usize, usize)>,
}
impl TreePath {
pub fn new() -> Self {
TreePath { path: vec![] }
}
pub fn push(&mut self, depth: usize, index: usize) {
self.path.push((depth, index));
}
pub fn pop(&mut self) {
self.path.pop();
}
}
pub struct IndexCounter {
current_index: usize,
}
impl IndexCounter {
pub fn new() -> Self {
IndexCounter { current_index: 0 }
}
pub fn next(&mut self) -> usize {
let current_index = self.current_index;
self.current_index += 1;
current_index
}
}
pub fn get_generic_id_and_type(tipo: &Type, param: &Type) -> Vec<(u64, Arc<Type>)> { pub fn get_generic_id_and_type(tipo: &Type, param: &Type) -> Vec<(u64, Arc<Type>)> {
let mut generics_ids = vec![]; let mut generics_ids = vec![];
@ -261,3 +296,401 @@ pub fn handle_clause_guard(clause_guard: &ClauseGuard<Arc<Type>>) -> AirTree {
ClauseGuard::Constant(constant) => constants_ir(constant), ClauseGuard::Constant(constant) => constants_ir(constant),
} }
} }
pub fn erase_opaque_operations(
air_tree: &mut AirTree,
data_types: &IndexMap<DataTypeKey, &TypedDataType>,
) {
traverse_tree_with(air_tree, &mut TreePath::new(), 0, 0, &|air_tree, _| {
if let AirTree::Expression(e) = air_tree {
match e {
AirExpression::Constr { tipo, args, .. } => {
if check_replaceable_opaque_type(tipo, data_types) {
*air_tree = args.pop().unwrap();
}
}
AirExpression::RecordAccess { tipo, record, .. } => {
if check_replaceable_opaque_type(tipo, data_types) {
*air_tree = (**record).clone();
}
}
_ => {}
}
} else if let AirTree::Statement {
statement:
AirStatement::FieldsExpose {
record, indices, ..
},
hoisted_over: Some(hoisted_over),
} = air_tree
{
let name = indices[0].1.clone();
if check_replaceable_opaque_type(&record.get_type(), data_types) {
*air_tree = AirTree::let_assignment(name, (**record).clone())
.hoist_over((**hoisted_over).clone())
}
}
});
}
fn traverse_tree_with(
air_tree: &mut AirTree,
tree_path: &mut TreePath,
current_depth: usize,
depth_index: usize,
with: &impl Fn(&mut AirTree, &TreePath),
) {
let mut index_count = IndexCounter::new();
tree_path.push(current_depth, depth_index);
match air_tree {
AirTree::Statement {
statement,
hoisted_over: Some(hoisted_over),
} => {
match statement {
AirStatement::Let { value, .. } => {
traverse_tree_with(
value,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirStatement::DefineFunc { func_body, .. } => {
traverse_tree_with(
func_body,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirStatement::AssertConstr { constr, .. } => {
traverse_tree_with(
constr,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirStatement::AssertBool { value, .. } => {
traverse_tree_with(
value,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirStatement::ClauseGuard { pattern, .. } => {
traverse_tree_with(
pattern,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirStatement::ListClauseGuard { .. } => {}
AirStatement::TupleGuard { .. } => {}
AirStatement::FieldsExpose { record, .. } => {
traverse_tree_with(
record,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirStatement::ListAccessor { list, .. } => {
traverse_tree_with(
list,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirStatement::ListExpose { .. } => {}
AirStatement::TupleAccessor { tuple, .. } => {
traverse_tree_with(
tuple,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirStatement::NoOp => {}
};
traverse_tree_with(
hoisted_over,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirTree::Expression(e) => match e {
AirExpression::List { items, .. } => {
for item in items {
traverse_tree_with(
item,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
}
AirExpression::Tuple { items, .. } => {
for item in items {
traverse_tree_with(
item,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
}
AirExpression::Var {
constructor,
name,
variant_name,
} => {
todo!()
}
AirExpression::Call { func, args, .. } => {
traverse_tree_with(func, tree_path, current_depth + 1, index_count.next(), with);
for arg in args {
traverse_tree_with(arg, tree_path, current_depth + 1, index_count.next(), with);
}
}
AirExpression::Fn { func_body, .. } => {
traverse_tree_with(
func_body,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::Builtin { args, .. } => {
for arg in args {
traverse_tree_with(arg, tree_path, current_depth + 1, index_count.next(), with);
}
}
AirExpression::BinOp { left, right, .. } => {
traverse_tree_with(left, tree_path, current_depth + 1, index_count.next(), with);
traverse_tree_with(
right,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::UnOp { arg, .. } => {
traverse_tree_with(arg, tree_path, current_depth + 1, index_count.next(), with);
}
AirExpression::UnWrapData { value, .. } => {
traverse_tree_with(
value,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::WrapData { value, .. } => {
traverse_tree_with(
value,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::When {
subject, clauses, ..
} => {
traverse_tree_with(
subject,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
traverse_tree_with(
clauses,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::Clause {
pattern,
then,
otherwise,
..
} => {
traverse_tree_with(
pattern,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
traverse_tree_with(then, tree_path, current_depth + 1, index_count.next(), with);
traverse_tree_with(
otherwise,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::ListClause {
then, otherwise, ..
} => {
traverse_tree_with(then, tree_path, current_depth + 1, index_count.next(), with);
traverse_tree_with(
otherwise,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::WrapClause { then, otherwise } => {
traverse_tree_with(then, tree_path, current_depth + 1, index_count.next(), with);
traverse_tree_with(
otherwise,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::TupleClause {
then, otherwise, ..
} => {
traverse_tree_with(then, tree_path, current_depth + 1, index_count.next(), with);
traverse_tree_with(
otherwise,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::Finally { pattern, then } => {
traverse_tree_with(
pattern,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
traverse_tree_with(then, tree_path, current_depth + 1, index_count.next(), with);
}
AirExpression::If {
pattern,
then,
otherwise,
..
} => {
traverse_tree_with(
pattern,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
traverse_tree_with(then, tree_path, current_depth + 1, index_count.next(), with);
traverse_tree_with(
otherwise,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::Constr { args, .. } => {
for arg in args {
traverse_tree_with(arg, tree_path, current_depth + 1, index_count.next(), with);
}
}
AirExpression::RecordUpdate { record, args, .. } => {
traverse_tree_with(
record,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
for arg in args {
traverse_tree_with(arg, tree_path, current_depth + 1, index_count.next(), with);
}
}
AirExpression::RecordAccess { record, .. } => {
traverse_tree_with(
record,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::TupleIndex { tuple, .. } => {
traverse_tree_with(
tuple,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::Trace { msg, then, .. } => {
traverse_tree_with(msg, tree_path, current_depth + 1, index_count.next(), with);
traverse_tree_with(then, tree_path, current_depth + 1, index_count.next(), with);
}
AirExpression::FieldsEmpty { constr } => {
traverse_tree_with(
constr,
tree_path,
current_depth + 1,
index_count.next(),
with,
);
}
AirExpression::ListEmpty { list } => {
traverse_tree_with(list, tree_path, current_depth + 1, index_count.next(), with);
}
_ => {}
},
_ => unreachable!(),
}
with(air_tree, tree_path);
tree_path.pop();
}

View File

@ -4,7 +4,7 @@ use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction};
use crate::{ use crate::{
ast::{BinOp, Span, UnOp}, ast::{BinOp, Span, UnOp},
builtins::{data, list, void}, builtins::{bool, byte_array, data, int, list, string, void},
tipo::{Type, ValueConstructor, ValueConstructorVariant}, tipo::{Type, ValueConstructor, ValueConstructorVariant},
}; };
@ -1130,4 +1130,50 @@ impl AirTree {
_ => unreachable!("FOUND UNHOISTED STATEMENT"), _ => unreachable!("FOUND UNHOISTED STATEMENT"),
} }
} }
pub fn get_type(&self) -> Arc<Type> {
match self {
AirTree::Statement {
hoisted_over: Some(hoisted_over),
..
} => hoisted_over.get_type(),
AirTree::Expression(e) => match e {
AirExpression::Int { .. } => int(),
AirExpression::String { .. } => string(),
AirExpression::ByteArray { .. } => byte_array(),
AirExpression::Bool { .. } => bool(),
AirExpression::List { tipo, .. }
| AirExpression::Tuple { tipo, .. }
| AirExpression::Call { tipo, .. }
| AirExpression::Builtin { tipo, .. }
| AirExpression::BinOp { tipo, .. }
| AirExpression::UnWrapData { tipo, .. }
| AirExpression::When { tipo, .. }
| AirExpression::If { tipo, .. }
| AirExpression::Constr { tipo, .. }
| AirExpression::RecordUpdate { tipo, .. }
| AirExpression::RecordAccess { tipo, .. }
| AirExpression::TupleIndex { tipo, .. }
| AirExpression::ErrorTerm { tipo }
| AirExpression::Trace { tipo, .. } => tipo.clone(),
AirExpression::Void => void(),
AirExpression::Var { constructor, .. } => constructor.tipo.clone(),
AirExpression::Fn { func_body, .. } => func_body.get_type(),
AirExpression::UnOp { op, .. } => match op {
UnOp::Not => bool(),
UnOp::Negate => int(),
},
AirExpression::WrapData { .. } => data(),
AirExpression::Clause { then, .. }
| AirExpression::ListClause { then, .. }
| AirExpression::WrapClause { then, .. }
| AirExpression::TupleClause { then, .. }
| AirExpression::Finally { then, .. } => then.get_type(),
AirExpression::FieldsEmpty { constr } => todo!(),
AirExpression::ListEmpty { list } => todo!(),
},
_ => unreachable!(),
}
}
} }