Use Delay error directly when casting from data without traces

This commit is contained in:
microproofs 2024-09-01 20:10:59 -04:00 committed by Kasey
parent 575f0f9a9a
commit 2be76d7cda
2 changed files with 37 additions and 18 deletions

View File

@ -52,6 +52,11 @@ use uplc::{
optimize::{aiken_optimize_and_intern, interner::CodeGenInterner, shrinker::NO_INLINE}, optimize::{aiken_optimize_and_intern, interner::CodeGenInterner, shrinker::NO_INLINE},
}; };
type Otherwise = Option<AirTree>;
const DELAY_ERROR: fn() -> AirTree =
|| AirTree::anon_func(vec![], AirTree::error(Type::void(), false), true);
#[derive(Clone)] #[derive(Clone)]
pub struct CodeGenerator<'a> { pub struct CodeGenerator<'a> {
#[allow(dead_code)] #[allow(dead_code)]
@ -974,7 +979,7 @@ impl<'a> CodeGenerator<'a> {
&mut index_map, &mut index_map,
pattern.location(), pattern.location(),
then, then,
otherwise, props.otherwise.clone(),
0, 0,
), ),
) )
@ -1017,7 +1022,7 @@ impl<'a> CodeGenerator<'a> {
&mut index_map, &mut index_map,
pattern.location(), pattern.location(),
then, then,
otherwise, props.otherwise.clone(),
0, 0,
), ),
) )
@ -1579,7 +1584,7 @@ impl<'a> CodeGenerator<'a> {
defined_data_types: &mut IndexMap<String, u64>, defined_data_types: &mut IndexMap<String, u64>,
location: Span, location: Span,
then: AirTree, then: AirTree,
otherwise: AirTree, otherwise: Otherwise,
depth: usize, depth: usize,
) -> AirTree { ) -> AirTree {
assert!( assert!(
@ -1689,7 +1694,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::local_var(&pair_name, inner_list_type.clone()), AirTree::local_var(&pair_name, inner_list_type.clone()),
true, true,
expect_fst, expect_fst,
otherwise.clone(), otherwise.unwrap_or_else(DELAY_ERROR),
), ),
), ),
true, true,
@ -1783,7 +1788,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::local_var(&tuple_name, tipo.clone()), AirTree::local_var(&tuple_name, tipo.clone()),
true, true,
then, then,
otherwise, otherwise.unwrap_or_else(DELAY_ERROR),
); );
AirTree::let_assignment(&tuple_name, value, tuple_access) AirTree::let_assignment(&tuple_name, value, tuple_access)
@ -1849,7 +1854,7 @@ impl<'a> CodeGenerator<'a> {
otherwise.clone(), otherwise.clone(),
depth + 1, depth + 1,
), ),
otherwise, otherwise.unwrap_or_else(DELAY_ERROR),
), ),
), ),
true, true,
@ -1951,7 +1956,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::local_var(&pair_name, tipo.clone()), AirTree::local_var(&pair_name, tipo.clone()),
true, true,
expect_fst, expect_fst,
otherwise, otherwise.unwrap_or_else(DELAY_ERROR),
); );
AirTree::let_assignment(&pair_name, value, pair_access) AirTree::let_assignment(&pair_name, value, pair_access)
@ -2000,12 +2005,14 @@ impl<'a> CodeGenerator<'a> {
vec![], vec![],
); );
let otherwise_delayed = AirTree::local_var("otherwise_delayed", Type::void()); let otherwise_delayed = otherwise
.as_ref()
.map(|_| AirTree::local_var("otherwise_delayed", Type::void()));
let is_never = data_type.is_never(); let is_never = data_type.is_never();
let constr_clauses = data_type.constructors.iter().enumerate().rfold( let constr_clauses = data_type.constructors.iter().enumerate().rfold(
otherwise_delayed.clone(), otherwise_delayed.clone().unwrap_or_else(DELAY_ERROR),
|acc, (index, constr)| { |acc, (index, constr)| {
// NOTE: For the Never type, we have an placeholder first constructor // NOTE: For the Never type, we have an placeholder first constructor
// that must be ignored. The Never type is considered to have only one // that must be ignored. The Never type is considered to have only one
@ -2052,7 +2059,7 @@ impl<'a> CodeGenerator<'a> {
tipo.clone(), tipo.clone(),
), ),
constr_then, constr_then,
otherwise_delayed.clone(), otherwise_delayed.clone().unwrap_or_else(DELAY_ERROR),
) )
} else { } else {
AirTree::fields_expose( AirTree::fields_expose(
@ -2066,7 +2073,7 @@ impl<'a> CodeGenerator<'a> {
), ),
true, true,
constr_then, constr_then,
otherwise_delayed.clone(), otherwise_delayed.clone().unwrap_or_else(DELAY_ERROR),
) )
}; };
@ -2119,11 +2126,15 @@ impl<'a> CodeGenerator<'a> {
let code_gen_func = CodeGenFunction::Function { let code_gen_func = CodeGenFunction::Function {
body: func_body, body: func_body,
params: vec![ params: if otherwise.is_some() {
vec![
"__param_0".to_string(), "__param_0".to_string(),
"then_delayed".to_string(), "then_delayed".to_string(),
"otherwise_delayed".to_string(), "otherwise_delayed".to_string(),
], ]
} else {
vec!["__param_0".to_string(), "then_delayed".to_string()]
},
}; };
self.code_gen_functions self.code_gen_functions
@ -2134,7 +2145,11 @@ impl<'a> CodeGenerator<'a> {
defined_data_types.insert(data_type_name.to_string(), 1); defined_data_types.insert(data_type_name.to_string(), 1);
} }
let args = vec![value, AirTree::anon_func(vec![], then, true), otherwise]; let args = if let Some(otherwise) = otherwise {
vec![value, AirTree::anon_func(vec![], then, true), otherwise]
} else {
vec![value, AirTree::anon_func(vec![], then, true)]
};
let module_fn = ValueConstructorVariant::ModuleFn { let module_fn = ValueConstructorVariant::ModuleFn {
name: data_type_name.to_string(), name: data_type_name.to_string(),

View File

@ -981,7 +981,11 @@ pub fn unknown_data_to_type(term: Term<Name>, field_type: &Type) -> Term<Name> {
.lambda("__list_data") .lambda("__list_data")
.apply(Term::unlist_data().apply(term)), .apply(Term::unlist_data().apply(term)),
Some(UplcType::Bool) => Term::unwrap_bool_or(term, |result| result, &Term::Error.delay()), Some(UplcType::Bool) => Term::unwrap_bool_or(term, |result| result, &Term::Error.delay()),
Some(UplcType::Unit) => Term::unwrap_void_or(term, |result| result, &Term::Error.delay()), Some(UplcType::Unit) => Term::unwrap_void_or(
term.as_var("val", |val| Term::Var(val)),
|result| result,
&Term::Error.delay(),
),
Some(UplcType::Data) | None => term, Some(UplcType::Data) | None => term,
} }