fixing bugs and edge cases
This commit is contained in:
parent
2f4319f162
commit
58b327e5b3
|
@ -173,11 +173,8 @@ impl<'a> CodeGenerator<'a> {
|
|||
let full_tree = self.hoist_functions_to_validator(air_tree);
|
||||
|
||||
// optimizations on air tree
|
||||
|
||||
let full_vec = full_tree.to_vec();
|
||||
|
||||
println!("FULL VEC {:#?}", full_vec);
|
||||
|
||||
let term = self.uplc_code_gen(full_vec);
|
||||
|
||||
self.finalize(term)
|
||||
|
@ -197,8 +194,8 @@ impl<'a> CodeGenerator<'a> {
|
|||
term,
|
||||
};
|
||||
|
||||
println!("Program: {}", program.to_pretty());
|
||||
program = aiken_optimize_and_intern(program);
|
||||
// println!("PROGRAM {}", program.to_pretty());
|
||||
|
||||
// This is very important to call here.
|
||||
// If this isn't done, re-using the same instance
|
||||
|
@ -1865,7 +1862,10 @@ impl<'a> CodeGenerator<'a> {
|
|||
*complex_clause = *complex_clause || elem_props.complex_clause;
|
||||
|
||||
air_elems.push(statement);
|
||||
if &elem_name != "_" {
|
||||
list_tail = Some((tail, elem_name.to_string()));
|
||||
}
|
||||
|
||||
defined_heads.push(elem_name)
|
||||
});
|
||||
|
||||
|
@ -1882,6 +1882,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
defined_heads
|
||||
.into_iter()
|
||||
.zip(defined_tails.into_iter())
|
||||
.filter(|(head, _)| head != "_")
|
||||
.map(|(head, tail)| (tail, head))
|
||||
.collect_vec(),
|
||||
list_tail,
|
||||
|
@ -2130,8 +2131,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
),
|
||||
);
|
||||
}
|
||||
println!("WE GOT SEQUENCE {:#?}", sequence);
|
||||
|
||||
(AirTree::void(), AirTree::UnhoistedSequence(sequence))
|
||||
}
|
||||
}
|
||||
|
@ -2384,9 +2383,10 @@ impl<'a> CodeGenerator<'a> {
|
|||
.get(&variant_name)
|
||||
.unwrap_or_else(|| panic!("Missing Function Variant Definition"));
|
||||
|
||||
if let UserFunction::Function(body, deps) = function {
|
||||
if let UserFunction::Function { body, deps, params } = function {
|
||||
let mut hoist_body = body.clone();
|
||||
let mut hoist_deps = deps.clone();
|
||||
let params = params.clone();
|
||||
|
||||
let mut tree_path = tree_path.clone();
|
||||
|
||||
|
@ -2407,11 +2407,20 @@ impl<'a> CodeGenerator<'a> {
|
|||
.get_mut(&variant_name)
|
||||
.expect("Missing Function Variant Definition");
|
||||
|
||||
*function = UserFunction::Function(hoist_body, hoist_deps);
|
||||
if params.is_empty() {
|
||||
validator_hoistable.push((key, variant_name));
|
||||
}
|
||||
|
||||
*function = UserFunction::Function {
|
||||
body: hoist_body,
|
||||
deps: hoist_deps,
|
||||
params,
|
||||
};
|
||||
} else {
|
||||
todo!("Deal with Link later")
|
||||
}
|
||||
}
|
||||
validator_hoistable.dedup();
|
||||
|
||||
// First we need to sort functions by dependencies
|
||||
// here's also where we deal with mutual recursion
|
||||
|
@ -2433,7 +2442,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
.unwrap_or_else(|| panic!("Missing Function Variant Definition"));
|
||||
|
||||
// TODO: change this part to handle mutual recursion
|
||||
if let UserFunction::Function(_, deps) = function {
|
||||
if let UserFunction::Function { deps, .. } = function {
|
||||
if function_has_params {
|
||||
for (dep_generic_func, dep_variant) in deps.iter() {
|
||||
if !(dep_generic_func == &generic_func && dep_variant == &variant) {
|
||||
|
@ -2501,9 +2510,13 @@ impl<'a> CodeGenerator<'a> {
|
|||
>,
|
||||
hoisted_functions: &mut Vec<(FunctionAccessKey, String)>,
|
||||
) {
|
||||
if let UserFunction::Function(body, func_deps) = function {
|
||||
if let UserFunction::Function {
|
||||
body,
|
||||
deps: func_deps,
|
||||
params,
|
||||
} = function
|
||||
{
|
||||
let mut body = body.clone();
|
||||
let node_to_edit = air_tree.find_air_tree_node(tree_path);
|
||||
|
||||
let (key, variant) = key_var;
|
||||
|
||||
|
@ -2513,28 +2526,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
.any(|(dep_key, dep_variant)| dep_key == key && dep_variant == variant);
|
||||
|
||||
// first grab dependencies
|
||||
let func_params = self
|
||||
.functions
|
||||
.get(key)
|
||||
.map(|func| {
|
||||
func.arguments
|
||||
.iter()
|
||||
.map(|func_arg| {
|
||||
func_arg
|
||||
.arg_name
|
||||
.get_variable_name()
|
||||
.unwrap_or("_")
|
||||
.to_string()
|
||||
})
|
||||
.collect_vec()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let Some(CodeGenFunction::Function { params, .. }) =
|
||||
self.code_gen_functions.get(&key.function_name)
|
||||
else { unreachable!() };
|
||||
|
||||
params.clone()
|
||||
});
|
||||
let func_params = params;
|
||||
|
||||
let params_empty = func_params.is_empty();
|
||||
|
||||
|
@ -2551,7 +2543,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
&key.function_name,
|
||||
&key.module_name,
|
||||
variant,
|
||||
func_params,
|
||||
func_params.clone(),
|
||||
is_recursive,
|
||||
body,
|
||||
);
|
||||
|
@ -2564,6 +2556,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
hoisted_functions,
|
||||
functions_to_hoist,
|
||||
);
|
||||
let node_to_edit = air_tree.find_air_tree_node(tree_path);
|
||||
|
||||
// now hoist full function onto validator tree
|
||||
*node_to_edit = function_deps.hoist_over(body.hoist_over(node_to_edit.clone()));
|
||||
|
@ -2630,34 +2623,15 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
// In the case of zero args, we need to hoist the dependency function to the top of the zero arg function
|
||||
if &dep_path.common_ancestor(func_path) == func_path || params_empty {
|
||||
let dependent_params = self
|
||||
.functions
|
||||
.get(&dep_key)
|
||||
.map(|dep_func| {
|
||||
dep_func
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|func_arg| {
|
||||
func_arg
|
||||
.arg_name
|
||||
.get_variable_name()
|
||||
.unwrap_or("_")
|
||||
.to_string()
|
||||
})
|
||||
.collect_vec()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let Some(CodeGenFunction::Function { params, .. }) =
|
||||
self.code_gen_functions.get(&dep_key.function_name)
|
||||
else { unreachable!() };
|
||||
|
||||
params.clone()
|
||||
});
|
||||
|
||||
let UserFunction::Function(mut dep_air_tree, dependency_deps) =
|
||||
let UserFunction::Function { body: mut dep_air_tree, deps: dependency_deps, params: dependent_params } =
|
||||
dep_function.clone()
|
||||
else { unreachable!() };
|
||||
|
||||
if dependent_params.is_empty() {
|
||||
// continue for zero arg functions. They are treated like global hoists.
|
||||
continue;
|
||||
}
|
||||
|
||||
let is_dependent_recursive = dependency_deps
|
||||
.iter()
|
||||
.any(|(key, variant)| &dep_key == key && &dep_variant == variant);
|
||||
|
@ -2666,8 +2640,8 @@ impl<'a> CodeGenerator<'a> {
|
|||
.iter()
|
||||
.filter(|(dep_k, dep_v)| !(dep_k == &dep_key && dep_v == &dep_variant))
|
||||
.filter(|(dep_k, dep_v)| {
|
||||
!params_empty
|
||||
&& !hoisted_functions
|
||||
params_empty
|
||||
|| !hoisted_functions
|
||||
.iter()
|
||||
.any(|(generic, variant)| generic == dep_k && variant == dep_v)
|
||||
})
|
||||
|
@ -2690,12 +2664,9 @@ impl<'a> CodeGenerator<'a> {
|
|||
));
|
||||
|
||||
deps_vec.extend(dependency_deps_to_add);
|
||||
|
||||
if !params_empty {
|
||||
hoisted_functions.push((dep_key.clone(), dep_variant.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dep_insertions.reverse();
|
||||
|
||||
|
@ -2800,7 +2771,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
let (path, _) = func_variants.get_mut("").unwrap();
|
||||
*path = path.common_ancestor(tree_path);
|
||||
} else {
|
||||
let CodeGenFunction::Function{ body, .. } = code_gen_func
|
||||
let CodeGenFunction::Function{ body, params } = code_gen_func
|
||||
else { unreachable!() };
|
||||
|
||||
let mut function_variant_path = IndexMap::new();
|
||||
|
@ -2809,7 +2780,11 @@ impl<'a> CodeGenerator<'a> {
|
|||
"".to_string(),
|
||||
(
|
||||
tree_path.clone(),
|
||||
UserFunction::Function(body.clone(), vec![]),
|
||||
UserFunction::Function {
|
||||
body: body.clone(),
|
||||
deps: vec![],
|
||||
params: params.clone(),
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -2831,17 +2806,20 @@ impl<'a> CodeGenerator<'a> {
|
|||
let mut function_def_types = function_def
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| &arg.tipo)
|
||||
.map(|arg| convert_opaque_type(&arg.tipo, &self.data_types))
|
||||
.collect_vec();
|
||||
|
||||
function_def_types.push(&function_def.return_type);
|
||||
function_def_types.push(convert_opaque_type(
|
||||
&function_def.return_type,
|
||||
&self.data_types,
|
||||
));
|
||||
|
||||
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)
|
||||
get_generic_id_and_type(&func_tipo, &var_tipo)
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
|
@ -2867,29 +2845,45 @@ impl<'a> CodeGenerator<'a> {
|
|||
if let Some((path, _)) = func_variants.get_mut(&variant) {
|
||||
*path = path.common_ancestor(tree_path);
|
||||
} else {
|
||||
let params = function_def
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
arg.arg_name.get_variable_name().unwrap_or("_").to_string()
|
||||
})
|
||||
.collect_vec();
|
||||
|
||||
let mut function_air_tree_body = self.build(&function_def.body);
|
||||
|
||||
function_air_tree_body.traverse_tree_with(&mut |air_tree, _| {
|
||||
monomorphize(air_tree, &mono_types);
|
||||
|
||||
erase_opaque_type_operations(air_tree, &self.data_types);
|
||||
monomorphize(air_tree, &mono_types);
|
||||
});
|
||||
|
||||
func_variants.insert(
|
||||
variant,
|
||||
(
|
||||
tree_path.clone(),
|
||||
UserFunction::Function(function_air_tree_body, vec![]),
|
||||
UserFunction::Function {
|
||||
body: function_air_tree_body,
|
||||
deps: vec![],
|
||||
params,
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let params = function_def
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| arg.arg_name.get_variable_name().unwrap_or("_").to_string())
|
||||
.collect_vec();
|
||||
|
||||
let mut function_air_tree_body = self.build(&function_def.body);
|
||||
|
||||
function_air_tree_body.traverse_tree_with(&mut |air_tree, _| {
|
||||
monomorphize(air_tree, &mono_types);
|
||||
|
||||
erase_opaque_type_operations(air_tree, &self.data_types);
|
||||
monomorphize(air_tree, &mono_types);
|
||||
});
|
||||
|
||||
let mut function_variant_path = IndexMap::new();
|
||||
|
@ -2898,7 +2892,11 @@ impl<'a> CodeGenerator<'a> {
|
|||
variant,
|
||||
(
|
||||
tree_path.clone(),
|
||||
UserFunction::Function(function_air_tree_body, vec![]),
|
||||
UserFunction::Function {
|
||||
body: function_air_tree_body,
|
||||
deps: vec![],
|
||||
params,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
@ -38,7 +38,11 @@ pub enum CodeGenFunction {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum UserFunction {
|
||||
Function(AirTree, Vec<(FunctionAccessKey, String)>),
|
||||
Function {
|
||||
body: AirTree,
|
||||
deps: Vec<(FunctionAccessKey, String)>,
|
||||
params: Vec<String>,
|
||||
},
|
||||
Link(String),
|
||||
}
|
||||
|
||||
|
@ -542,7 +546,7 @@ pub fn erase_opaque_type_operations(
|
|||
}
|
||||
}
|
||||
AirExpression::RecordAccess { tipo, record, .. } => {
|
||||
if check_replaceable_opaque_type(tipo, data_types) {
|
||||
if check_replaceable_opaque_type(&record.return_type(), data_types) {
|
||||
*air_tree = (**record).clone();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,8 @@ fn assert_uplc(source_code: &str, expected: Term<Name>, should_fail: bool) {
|
|||
|
||||
let expected = optimize::aiken_optimize_and_intern(expected);
|
||||
|
||||
// println!("expected: {}", expected.to_pretty());
|
||||
|
||||
let expected: Program<DeBruijn> = expected.try_into().unwrap();
|
||||
|
||||
assert_eq!(debruijn_program.to_pretty(), expected.to_pretty());
|
||||
|
@ -477,7 +479,7 @@ fn acceptance_test_5_direct_2_heads() {
|
|||
when xs is {
|
||||
[] -> None
|
||||
[a] -> Some(xs)
|
||||
[a, b, ..c] -> Some([a,b])
|
||||
[a, b, ..] -> Some([a,b])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,11 +497,58 @@ fn acceptance_test_5_direct_2_heads() {
|
|||
Term::var("xs")
|
||||
.delayed_choose_list(
|
||||
Term::Constant(Constant::Data(Data::constr(1, vec![])).into()),
|
||||
Term::constr_data().apply(Term::integer(0.into())).apply(
|
||||
Term::var("tail_1")
|
||||
.delayed_choose_list(
|
||||
Term::constr_data()
|
||||
.apply(Term::integer(0.into()))
|
||||
.apply(
|
||||
Term::mk_cons()
|
||||
.apply(Term::head_list().apply(Term::var("xs")))
|
||||
.apply(Term::list_data().apply(Term::var("xs")))
|
||||
.apply(Term::empty_list()),
|
||||
)
|
||||
.lambda("a")
|
||||
.apply(
|
||||
Term::un_i_data().apply(
|
||||
Term::head_list().apply(Term::var("xs")),
|
||||
),
|
||||
),
|
||||
Term::constr_data()
|
||||
.apply(Term::integer(0.into()))
|
||||
.apply(
|
||||
Term::mk_cons()
|
||||
.apply(
|
||||
Term::list_data().apply(
|
||||
Term::mk_cons()
|
||||
.apply(
|
||||
Term::i_data()
|
||||
.apply(Term::var("a")),
|
||||
)
|
||||
.apply(
|
||||
Term::mk_cons()
|
||||
.apply(
|
||||
Term::i_data().apply(
|
||||
Term::var("b"),
|
||||
),
|
||||
)
|
||||
.apply(Term::empty_list()),
|
||||
),
|
||||
),
|
||||
)
|
||||
.apply(Term::empty_list()),
|
||||
)
|
||||
.lambda("b")
|
||||
.apply(Term::un_i_data().apply(
|
||||
Term::head_list().apply(Term::var("tail_1")),
|
||||
))
|
||||
.lambda("a")
|
||||
.apply(
|
||||
Term::un_i_data().apply(
|
||||
Term::head_list().apply(Term::var("xs")),
|
||||
),
|
||||
),
|
||||
)
|
||||
.lambda("tail_1")
|
||||
.apply(Term::tail_list().apply(Term::var("xs"))),
|
||||
)
|
||||
.lambda("xs"),
|
||||
)
|
||||
|
@ -510,7 +559,14 @@ fn acceptance_test_5_direct_2_heads() {
|
|||
])),
|
||||
)
|
||||
.apply(Term::Constant(
|
||||
Constant::Data(Data::constr(0, vec![Data::integer(1.into())])).into(),
|
||||
Constant::Data(Data::constr(
|
||||
0,
|
||||
vec![Data::list(vec![
|
||||
Data::integer(1.into()),
|
||||
Data::integer(2.into()),
|
||||
])],
|
||||
))
|
||||
.into(),
|
||||
)),
|
||||
false,
|
||||
);
|
||||
|
@ -749,14 +805,14 @@ fn acceptance_test_7_unzip() {
|
|||
.apply(Term::var("unzip"))
|
||||
.apply(Term::var("rest")),
|
||||
)
|
||||
.lambda("a")
|
||||
.apply(Term::un_i_data().apply(
|
||||
Term::fst_pair().apply(Term::var("head_pair")),
|
||||
))
|
||||
.lambda("b")
|
||||
.apply(Term::un_b_data().apply(
|
||||
Term::snd_pair().apply(Term::var("head_pair")),
|
||||
))
|
||||
.lambda("a")
|
||||
.apply(Term::un_i_data().apply(
|
||||
Term::fst_pair().apply(Term::var("head_pair")),
|
||||
))
|
||||
.lambda("rest")
|
||||
.apply(Term::tail_list().apply(Term::var("xs")))
|
||||
.lambda("head_pair")
|
||||
|
|
Loading…
Reference in New Issue