From 9704cafefea58042ae3248ea91da6b2f1a2a5c18 Mon Sep 17 00:00:00 2001 From: microproofs Date: Thu, 13 Jul 2023 15:28:38 -0400 Subject: [PATCH] a checkpoint for function hoisting start and type fix --- crates/aiken-lang/src/builtins.rs | 4 - crates/aiken-lang/src/gen_uplc.rs | 19 +- crates/aiken-lang/src/gen_uplc/builder.rs | 5 +- crates/aiken-lang/src/gen_uplc2.rs | 615 ++++++++++++++++++--- crates/aiken-lang/src/gen_uplc2/builder.rs | 439 ++++++++++++++- crates/aiken-lang/src/gen_uplc2/tree.rs | 48 +- 6 files changed, 1022 insertions(+), 108 deletions(-) diff --git a/crates/aiken-lang/src/builtins.rs b/crates/aiken-lang/src/builtins.rs index 39e5c9d0..24903d9a 100644 --- a/crates/aiken-lang/src/builtins.rs +++ b/crates/aiken-lang/src/builtins.rs @@ -671,7 +671,6 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap IndexMap IndexMap IndexMap CodeGenerator<'a> { let func = self.functions.get(&FunctionAccessKey { module_name: module_name.clone(), function_name: name.clone(), - variant_name: String::new(), }); let type_info = self.module_types.get(module_name).unwrap(); @@ -3068,7 +3067,7 @@ impl<'a> CodeGenerator<'a> { func_stack.define_func( function_access_key.function_name.clone(), function_access_key.module_name.clone(), - function_access_key.variant_name.clone(), + "", func_comp.args.clone(), func_comp.recursive, recursion_stack, @@ -3112,7 +3111,7 @@ impl<'a> CodeGenerator<'a> { let mut skip = false; for ir in function_ir.clone() { - let Air::Var { constructor, variant_name, .. } = ir + let Air::Var { constructor, .. } = ir else { continue; }; @@ -3125,7 +3124,6 @@ impl<'a> CodeGenerator<'a> { let ir_function_key = FunctionAccessKey { module_name: module.clone(), function_name: func_name.clone(), - variant_name: variant_name.clone(), }; 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 { module_name: module.clone(), function_name: name.clone(), - variant_name: String::new(), }; if let Some(function) = self.functions.get(&non_variant_function_key).cloned() { @@ -3243,7 +3240,6 @@ impl<'a> CodeGenerator<'a> { let function_key = FunctionAccessKey { module_name: module.clone(), function_name: non_variant_function_key.function_name, - variant_name: variant_name.clone(), }; ir_stack[index] = Air::Var { @@ -3278,13 +3274,11 @@ impl<'a> CodeGenerator<'a> { let current_func = FunctionAccessKey { module_name: module.clone(), function_name: func_name.clone(), - variant_name: String::new(), }; let current_func_as_variant = FunctionAccessKey { module_name: module.clone(), function_name: func_name.clone(), - variant_name: variant_name.clone(), }; let function = self.functions.get(¤t_func); @@ -3335,7 +3329,6 @@ impl<'a> CodeGenerator<'a> { FunctionAccessKey { module_name: current_func.module_name, function_name: current_func.function_name, - variant_name, }, (), ); @@ -3394,7 +3387,6 @@ impl<'a> CodeGenerator<'a> { let function_key = FunctionAccessKey { module_name: "".to_string(), function_name: name.to_string(), - variant_name: "".to_string(), }; let function_stack = AirStack { @@ -3416,7 +3408,6 @@ impl<'a> CodeGenerator<'a> { .map(|item| FunctionAccessKey { module_name: "".to_string(), function_name: item, - variant_name: "".to_string(), }) .collect_vec(), recursive: false, @@ -4178,14 +4169,12 @@ impl<'a> CodeGenerator<'a> { FunctionAccessKey { module_name, function_name, - variant_name, }, ir, ) in zero_arg_functions.into_iter() { - let name_module = - format!("{module_name}_{function_name}{variant_name}"); - let name = format!("{function_name}{variant_name}"); + let name_module = format!("{module_name}_{function_name}"); + let name = function_name.to_string(); if text == &name || text == &name_module { let mut term = self.uplc_code_gen(&mut ir.clone()); term = term diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index 2744be77..33d3b4e3 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -53,7 +53,6 @@ pub type ConstrUsageKey = String; pub struct FunctionAccessKey { pub module_name: String, pub function_name: String, - pub variant_name: String, } #[derive(Clone, Debug)] @@ -766,7 +765,6 @@ pub fn match_ir_for_recursion( let var_func_access = FunctionAccessKey { module_name: module, function_name: func_name.clone(), - variant_name: variant_name.clone(), }; if function_access_key.clone() == var_func_access { @@ -1571,7 +1569,7 @@ pub fn handle_func_dependencies( temp_stack.define_func( dependency.function_name.clone(), dependency.module_name.clone(), - dependency.variant_name.clone(), + "", depend_comp.args.clone(), depend_comp.recursive, recursion_stack, @@ -1607,7 +1605,6 @@ pub fn handle_recursion_ir( &FunctionAccessKey { function_name: func_key.function_name.clone(), module_name: func_key.module_name.clone(), - variant_name: func_key.variant_name.clone(), }, index, ); diff --git a/crates/aiken-lang/src/gen_uplc2.rs b/crates/aiken-lang/src/gen_uplc2.rs index c3883503..99df8146 100644 --- a/crates/aiken-lang/src/gen_uplc2.rs +++ b/crates/aiken-lang/src/gen_uplc2.rs @@ -25,14 +25,20 @@ use crate::{ 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::{ ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor, ValueConstructorVariant, }, }; -use self::tree::{AirExpression, AirTree}; +use self::{ + builder::{IndexCounter, TreePath}, + tree::{AirExpression, AirStatement, AirTree}, +}; #[derive(Clone, Debug)] pub enum CodeGenFunction { @@ -40,6 +46,12 @@ pub enum CodeGenFunction { Link(String), } +#[derive(Clone, Debug)] +pub enum UserFunction { + Function(AirTree, Term), + Link(String), +} + #[derive(Clone)] pub struct CodeGenerator<'a> { defined_functions: IndexMap, @@ -94,7 +106,7 @@ impl<'a> CodeGenerator<'a> { println!("{:#?}", validator_args_tree); 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!() } @@ -106,6 +118,8 @@ impl<'a> CodeGenerator<'a> { println!("{:#?}", air_tree); println!("{:#?}", air_tree.to_vec()); + let full_tree = self.hoist_functions(air_tree); + todo!() } @@ -222,7 +236,6 @@ impl<'a> CodeGenerator<'a> { } TypedExpr::ModuleSelect { - tipo, module_name, constructor: ModuleValueConstructor::Fn { name, .. }, .. @@ -273,8 +286,12 @@ impl<'a> CodeGenerator<'a> { } }, TypedExpr::BinOp { - name, left, right, .. - } => AirTree::binop(*name, left.tipo(), self.build(left), self.build(right)), + name, + left, + right, + tipo, + .. + } => AirTree::binop(*name, tipo.clone(), self.build(left), self.build(right)), TypedExpr::Assignment { tipo, @@ -360,6 +377,7 @@ impl<'a> CodeGenerator<'a> { &clauses, last_clause, &subject.tipo(), + tipo, &mut ClauseProperties::init( &subject.tipo(), constr_var.clone(), @@ -370,8 +388,8 @@ impl<'a> CodeGenerator<'a> { let constr_assign = AirTree::let_assignment(&constr_var, self.build(subject)); let when_assign = AirTree::when( subject_name, - subject.tipo(), - AirTree::local_var(constr_var, tipo.clone()), + tipo.clone(), + AirTree::local_var(constr_var, subject.tipo()), clauses, ); @@ -438,7 +456,6 @@ impl<'a> CodeGenerator<'a> { let func = self.functions.get(&FunctionAccessKey { module_name: module_name.clone(), function_name: name.clone(), - variant_name: String::new(), }); let type_info = self.module_types.get(module_name).unwrap(); @@ -549,7 +566,7 @@ impl<'a> CodeGenerator<'a> { Pattern::Var { name, .. } => { if props.full_check { 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 val = AirTree::local_var(name, tipo.clone()); @@ -558,7 +575,7 @@ impl<'a> CodeGenerator<'a> { AirTree::let_assignment(name, assignment.hoist_over(val)) } else { let expect = self.expect_type_assign( - &tipo, + &non_opaque_tipo, val.clone(), &mut index_map, pattern.location(), @@ -1159,7 +1176,7 @@ impl<'a> CodeGenerator<'a> { .flat_map(|item| get_generic_id_and_type(item.0, &item.1)) .collect() } else { - vec![].into_iter().collect() + IndexMap::new() }; let data_type_name = format!("__expect_{}_{}", data_type.name, data_type_variant); @@ -1339,6 +1356,7 @@ impl<'a> CodeGenerator<'a> { clauses: &[TypedClause], final_clause: TypedClause, subject_tipo: &Arc, + return_tipo: &Arc, props: &mut ClauseProperties, ) -> AirTree { assert!( @@ -1396,6 +1414,7 @@ impl<'a> CodeGenerator<'a> { rest_clauses, final_clause, subject_tipo, + return_tipo, &mut next_clause_props, ), complex_clause, @@ -1407,6 +1426,7 @@ impl<'a> CodeGenerator<'a> { rest_clauses, final_clause, subject_tipo, + return_tipo, &mut next_clause_props, ), ) @@ -1421,6 +1441,7 @@ impl<'a> CodeGenerator<'a> { rest_clauses, final_clause, subject_tipo, + return_tipo, &mut next_clause_props, ), complex_clause, @@ -1456,6 +1477,7 @@ impl<'a> CodeGenerator<'a> { rest_clauses, final_clause, subject_tipo, + return_tipo, &mut next_clause_props, ), ); @@ -1532,6 +1554,7 @@ impl<'a> CodeGenerator<'a> { rest_clauses, final_clause, subject_tipo, + return_tipo, &mut next_clause_props, ), ) @@ -1544,6 +1567,7 @@ impl<'a> CodeGenerator<'a> { rest_clauses, final_clause, subject_tipo, + return_tipo, &mut next_clause_props, ), next_tail_name, @@ -1587,6 +1611,7 @@ impl<'a> CodeGenerator<'a> { rest_clauses, final_clause, subject_tipo, + return_tipo, &mut next_clause_props, ), ) @@ -1601,6 +1626,7 @@ impl<'a> CodeGenerator<'a> { rest_clauses, final_clause, subject_tipo, + return_tipo, &mut next_clause_props, ), props.complex_clause, @@ -2194,14 +2220,18 @@ impl<'a> CodeGenerator<'a> { 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 function_holder = IndexMap::new(); + erase_opaque_operations(&mut air_tree, &self.data_types); + self.find_function_vars_and_depth( - &mut validator_args_tree, + &air_tree, &mut functions_to_hoist, &mut function_holder, + &mut TreePath::new(), + 0, 0, ); @@ -2210,17 +2240,141 @@ impl<'a> CodeGenerator<'a> { fn find_function_vars_and_depth( &mut self, - validator_args_tree: &mut AirTree, - function_usage: &mut IndexMap, - function_holder: &mut IndexMap, + validator_args_tree: &AirTree, + function_usage: &mut IndexMap>, + function_holder: &mut IndexMap>, + tree_path: &mut TreePath, current_depth: usize, + depth_index: usize, ) { + let mut index_count = IndexCounter::new(); + tree_path.push(current_depth, depth_index); match validator_args_tree { AirTree::Statement { statement, 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 { + 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 { constructor, name, @@ -2235,10 +2389,48 @@ impl<'a> CodeGenerator<'a> { else { return }; let function_var_tipo = &constructor.tipo; + println!("FUNCTION VAR TYPE {:#?}", function_var_tipo); + let generic_function_key = FunctionAccessKey { module_name: module.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> = 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!() @@ -2248,7 +2440,9 @@ impl<'a> CodeGenerator<'a> { func, function_usage, function_holder, + tree_path, current_depth + 1, + index_count.next(), ); for arg in args { @@ -2256,86 +2450,345 @@ impl<'a> CodeGenerator<'a> { arg, function_usage, function_holder, + tree_path, current_depth + 1, + index_count.next(), ); } } - AirExpression::Fn { params, func_body } => todo!(), - AirExpression::Builtin { func, tipo, args } => todo!(), - AirExpression::BinOp { - name, - tipo, - left, - right, - } => todo!(), - AirExpression::UnOp { op, arg } => todo!(), - AirExpression::UnWrapData { tipo, value } => todo!(), - AirExpression::WrapData { tipo, value } => todo!(), + AirExpression::Fn { func_body, .. } => { + self.find_function_vars_and_depth( + func_body, + function_usage, + 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, + function_usage, + function_holder, + tree_path, + current_depth + 1, + index_count.next(), + ); + + self.find_function_vars_and_depth( + right, + function_usage, + function_holder, + tree_path, + 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 { - tipo, - subject_name, - subject, - clauses, - } => todo!(), + subject, clauses, .. + } => { + self.find_function_vars_and_depth( + subject, + function_usage, + function_holder, + tree_path, + current_depth + 1, + index_count.next(), + ); + + self.find_function_vars_and_depth( + clauses, + function_usage, + function_holder, + tree_path, + current_depth + 1, + index_count.next(), + ); + } AirExpression::Clause { - tipo, - subject_name, - complex_clause, pattern, then, 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 { - tipo, - tail_name, - next_tail_name, - complex_clause, - then, - otherwise, - } => todo!(), - AirExpression::WrapClause { then, otherwise } => todo!(), + 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::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 { - tipo, - indices, - predefined_indices, - subject_name, - type_count, - complex_clause, - then, - otherwise, - } => todo!(), - AirExpression::Finally { pattern, then } => todo!(), + 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::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 { - tipo, pattern, then, otherwise, - } => todo!(), - AirExpression::Constr { tag, tipo, args } => todo!(), - AirExpression::RecordUpdate { - highest_index, - indices, - tipo, - record, - args, - } => todo!(), - AirExpression::RecordAccess { - field_index, - tipo, - record, - } => todo!(), - AirExpression::TupleIndex { - tipo, - tuple_index, - tuple, - } => todo!(), - AirExpression::ErrorTerm { tipo } => todo!(), - AirExpression::Trace { tipo, msg, then } => todo!(), - AirExpression::FieldsEmpty { constr } => todo!(), - AirExpression::ListEmpty { list } => 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::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, + function_usage, + function_holder, + tree_path, + current_depth + 1, + 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, + function_usage, + function_holder, + tree_path, + current_depth + 1, + index_count.next(), + ); + } + AirExpression::TupleIndex { tuple, .. } => { + self.find_function_vars_and_depth( + tuple, + function_usage, + function_holder, + tree_path, + current_depth + 1, + 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!(), } + tree_path.pop(); } } diff --git a/crates/aiken-lang/src/gen_uplc2/builder.rs b/crates/aiken-lang/src/gen_uplc2/builder.rs index d2bad701..290ce86f 100644 --- a/crates/aiken-lang/src/gen_uplc2/builder.rs +++ b/crates/aiken-lang/src/gen_uplc2/builder.rs @@ -3,8 +3,8 @@ use indexmap::IndexMap; use crate::{ ast::TypedDataType, builtins::bool, - gen_uplc::builder::{lookup_data_type_by_tipo, DataTypeKey}, - tipo::TypeVar, + gen_uplc::builder::{lookup_data_type_by_tipo, DataTypeKey, FunctionAccessKey}, + tipo::{TypeVar, ValueConstructorVariant}, }; use std::sync::Arc; @@ -13,7 +13,42 @@ use crate::{ 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)> { let mut generics_ids = vec![]; @@ -261,3 +296,401 @@ pub fn handle_clause_guard(clause_guard: &ClauseGuard>) -> AirTree { ClauseGuard::Constant(constant) => constants_ir(constant), } } + +pub fn erase_opaque_operations( + air_tree: &mut AirTree, + data_types: &IndexMap, +) { + 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(); +} diff --git a/crates/aiken-lang/src/gen_uplc2/tree.rs b/crates/aiken-lang/src/gen_uplc2/tree.rs index bd7ef31b..954bbf6e 100644 --- a/crates/aiken-lang/src/gen_uplc2/tree.rs +++ b/crates/aiken-lang/src/gen_uplc2/tree.rs @@ -4,7 +4,7 @@ use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction}; use crate::{ ast::{BinOp, Span, UnOp}, - builtins::{data, list, void}, + builtins::{bool, byte_array, data, int, list, string, void}, tipo::{Type, ValueConstructor, ValueConstructorVariant}, }; @@ -1130,4 +1130,50 @@ impl AirTree { _ => unreachable!("FOUND UNHOISTED STATEMENT"), } } + + pub fn get_type(&self) -> Arc { + 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!(), + } + } }