feat: Rework codegen traces to prevent repeated messages from taking up uplc script space
This commit is contained in:
parent
44021cde19
commit
7a6ddc45a0
|
@ -22,13 +22,14 @@ use crate::{
|
|||
AssignmentKind, BinOp, Pattern, Span, TypedArg, TypedClause, TypedDataType, TypedFunction,
|
||||
TypedPattern, TypedValidator, UnOp,
|
||||
},
|
||||
builtins::{bool, data, int, list, void},
|
||||
builtins::{bool, data, int, list, string, void},
|
||||
expr::TypedExpr,
|
||||
gen_uplc::builder::{
|
||||
check_replaceable_opaque_type, convert_opaque_type, erase_opaque_type_operations,
|
||||
find_and_replace_generics, find_list_clause_or_default_first, get_arg_type_name,
|
||||
get_generic_id_and_type, get_variant_name, monomorphize, pattern_has_conditions,
|
||||
wrap_as_multi_validator, wrap_validator_condition, CodeGenFunction, SpecificClause,
|
||||
CONSTR_INDEX_MISMATCH,
|
||||
},
|
||||
tipo::{
|
||||
ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
|
||||
|
@ -42,8 +43,9 @@ use self::{
|
|||
builder::{
|
||||
cast_validator_args, constants_ir, convert_type_to_data, extract_constant,
|
||||
lookup_data_type_by_tipo, modify_cyclic_calls, modify_self_calls, rearrange_list_clauses,
|
||||
AssignmentProperties, ClauseProperties, CycleFunctionNames, DataTypeKey, FunctionAccessKey,
|
||||
HoistableFunction, Variant,
|
||||
AssignmentProperties, ClauseProperties, CodeGenSpecialFuncs, CycleFunctionNames,
|
||||
DataTypeKey, FunctionAccessKey, HoistableFunction, Variant, CONSTR_NOT_EMPTY,
|
||||
INCORRECT_BOOLEAN, INCORRECT_CONSTR, LIST_NOT_EMPTY, TOO_MANY_ITEMS,
|
||||
},
|
||||
tree::{AirExpression, AirTree, TreePath},
|
||||
};
|
||||
|
@ -54,7 +56,7 @@ pub struct CodeGenerator<'a> {
|
|||
functions: IndexMap<FunctionAccessKey, &'a TypedFunction>,
|
||||
data_types: IndexMap<DataTypeKey, &'a TypedDataType>,
|
||||
module_types: IndexMap<&'a String, &'a TypeInfo>,
|
||||
needs_field_access: bool,
|
||||
special_functions: CodeGenSpecialFuncs,
|
||||
code_gen_functions: IndexMap<String, CodeGenFunction>,
|
||||
zero_arg_functions: IndexMap<(FunctionAccessKey, Variant), Vec<Air>>,
|
||||
cyclic_functions:
|
||||
|
@ -75,7 +77,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
functions,
|
||||
data_types,
|
||||
module_types,
|
||||
needs_field_access: false,
|
||||
special_functions: CodeGenSpecialFuncs::new(),
|
||||
code_gen_functions: IndexMap::new(),
|
||||
zero_arg_functions: IndexMap::new(),
|
||||
cyclic_functions: IndexMap::new(),
|
||||
|
@ -87,7 +89,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
pub fn reset(&mut self) {
|
||||
self.code_gen_functions = IndexMap::new();
|
||||
self.zero_arg_functions = IndexMap::new();
|
||||
self.needs_field_access = false;
|
||||
self.special_functions = CodeGenSpecialFuncs::new();
|
||||
self.defined_functions = IndexMap::new();
|
||||
self.cyclic_functions = IndexMap::new();
|
||||
self.id_gen = IdGenerator::new();
|
||||
|
@ -160,9 +162,11 @@ impl<'a> CodeGenerator<'a> {
|
|||
(term, other_term)
|
||||
};
|
||||
|
||||
term = wrap_as_multi_validator(spend, mint);
|
||||
// Special Case with multi_validators
|
||||
self.special_functions.use_function(CONSTR_FIELDS_EXPOSER);
|
||||
self.special_functions.use_function(CONSTR_INDEX_EXPOSER);
|
||||
|
||||
self.needs_field_access = true;
|
||||
term = wrap_as_multi_validator(spend, mint);
|
||||
}
|
||||
|
||||
term = cast_validator_args(term, params);
|
||||
|
@ -186,9 +190,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
}
|
||||
|
||||
fn finalize(&mut self, mut term: Term<Name>) -> Program<Name> {
|
||||
if self.needs_field_access {
|
||||
term = term.constr_fields_exposer().constr_index_exposer();
|
||||
}
|
||||
term = self.special_functions.apply_used_functions(term);
|
||||
|
||||
// TODO: Once SOP is implemented, new version is 1.1.0
|
||||
let mut program = Program {
|
||||
|
@ -547,7 +549,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
if check_replaceable_opaque_type(&record.tipo(), &self.data_types) {
|
||||
self.build(record)
|
||||
} else {
|
||||
self.needs_field_access = true;
|
||||
let function_name = format!("__access_index_{}", *index);
|
||||
|
||||
if self.code_gen_functions.get(&function_name).is_none() {
|
||||
|
@ -573,7 +574,10 @@ impl<'a> CodeGenerator<'a> {
|
|||
}
|
||||
|
||||
let list_of_fields = AirTree::call(
|
||||
AirTree::local_var(CONSTR_FIELDS_EXPOSER, void()),
|
||||
AirTree::local_var(
|
||||
self.special_functions.use_function(CONSTR_FIELDS_EXPOSER),
|
||||
void(),
|
||||
),
|
||||
list(data()),
|
||||
vec![self.build(record)],
|
||||
);
|
||||
|
@ -1468,7 +1472,10 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
let error_term = if self.tracing {
|
||||
AirTree::trace(
|
||||
AirTree::string("Constr index didn't match a type variant"),
|
||||
AirTree::local_var(
|
||||
self.special_functions.use_function(CONSTR_INDEX_MISMATCH),
|
||||
string(),
|
||||
),
|
||||
tipo.clone(),
|
||||
AirTree::error(tipo.clone(), false),
|
||||
)
|
||||
|
@ -3819,31 +3826,44 @@ impl<'a> CodeGenerator<'a> {
|
|||
id_list.push(self.id_gen.next());
|
||||
}
|
||||
|
||||
let inner_types = tipo
|
||||
let names_empty = names.is_empty();
|
||||
|
||||
let names_types = tipo
|
||||
.get_inner_types()
|
||||
.into_iter()
|
||||
.cycle()
|
||||
.take(names.len())
|
||||
.zip(names)
|
||||
.map(|(tipo, name)| (name, tipo))
|
||||
.collect_vec();
|
||||
|
||||
if !names.is_empty() {
|
||||
if !names_empty {
|
||||
let error_term = if self.tracing {
|
||||
Term::Error.trace(Term::var(
|
||||
self.special_functions.use_function(TOO_MANY_ITEMS),
|
||||
))
|
||||
} else {
|
||||
Term::Error
|
||||
};
|
||||
|
||||
term = builder::list_access_to_uplc(
|
||||
&names,
|
||||
&names_types,
|
||||
&id_list,
|
||||
tail,
|
||||
0,
|
||||
term,
|
||||
inner_types,
|
||||
check_last_item,
|
||||
true,
|
||||
self.tracing,
|
||||
error_term,
|
||||
)
|
||||
.apply(value);
|
||||
|
||||
arg_stack.push(term);
|
||||
} else if check_last_item {
|
||||
let trace_term = if self.tracing {
|
||||
Term::Error.trace(Term::string("Expected no items for List"))
|
||||
Term::Error.trace(Term::var(
|
||||
self.special_functions.use_function(LIST_NOT_EMPTY),
|
||||
))
|
||||
} else {
|
||||
Term::Error
|
||||
};
|
||||
|
@ -4323,20 +4343,24 @@ impl<'a> CodeGenerator<'a> {
|
|||
arg_stack.push(term);
|
||||
}
|
||||
Air::AssertConstr { constr_index } => {
|
||||
self.needs_field_access = true;
|
||||
let constr = arg_stack.pop().unwrap();
|
||||
|
||||
let mut term = arg_stack.pop().unwrap();
|
||||
|
||||
let trace_term = if self.tracing {
|
||||
Term::Error.trace(Term::string("Expected on incorrect Constr variant"))
|
||||
Term::Error.trace(Term::var(
|
||||
self.special_functions.use_function(INCORRECT_CONSTR),
|
||||
))
|
||||
} else {
|
||||
Term::Error
|
||||
};
|
||||
|
||||
term = Term::equals_integer()
|
||||
.apply(Term::integer(constr_index.into()))
|
||||
.apply(Term::var(CONSTR_INDEX_EXPOSER).apply(constr))
|
||||
.apply(
|
||||
Term::var(self.special_functions.use_function(CONSTR_INDEX_EXPOSER))
|
||||
.apply(constr),
|
||||
)
|
||||
.delayed_if_else(term, trace_term);
|
||||
|
||||
arg_stack.push(term);
|
||||
|
@ -4346,7 +4370,9 @@ impl<'a> CodeGenerator<'a> {
|
|||
let mut term = arg_stack.pop().unwrap();
|
||||
|
||||
let trace_term = if self.tracing {
|
||||
Term::Error.trace(Term::string("Expected on incorrect bool variant"))
|
||||
Term::Error.trace(Term::var(
|
||||
self.special_functions.use_function(INCORRECT_BOOLEAN),
|
||||
))
|
||||
} else {
|
||||
Term::Error
|
||||
};
|
||||
|
@ -4375,8 +4401,8 @@ impl<'a> CodeGenerator<'a> {
|
|||
{
|
||||
subject
|
||||
} else {
|
||||
self.needs_field_access = true;
|
||||
Term::var(CONSTR_INDEX_EXPOSER).apply(subject)
|
||||
Term::var(self.special_functions.use_function(CONSTR_INDEX_EXPOSER))
|
||||
.apply(subject)
|
||||
};
|
||||
|
||||
let mut term = arg_stack.pop().unwrap();
|
||||
|
@ -4576,10 +4602,10 @@ impl<'a> CodeGenerator<'a> {
|
|||
} else if tipo.is_list() || tipo.is_tuple() {
|
||||
unreachable!()
|
||||
} else {
|
||||
self.needs_field_access = true;
|
||||
Term::equals_integer()
|
||||
.apply(checker)
|
||||
.apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var(subject_name)))
|
||||
Term::equals_integer().apply(checker).apply(
|
||||
Term::var(self.special_functions.use_function(CONSTR_INDEX_EXPOSER))
|
||||
.apply(Term::var(subject_name)),
|
||||
)
|
||||
};
|
||||
|
||||
let term = condition
|
||||
|
@ -4721,7 +4747,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
indices,
|
||||
check_last_item,
|
||||
} => {
|
||||
self.needs_field_access = true;
|
||||
let mut id_list = vec![];
|
||||
|
||||
let value = arg_stack.pop().unwrap();
|
||||
|
@ -4736,33 +4761,48 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
let current_index = 0;
|
||||
|
||||
let names = indices.iter().cloned().map(|item| item.1).collect_vec();
|
||||
let inner_types = indices.iter().cloned().map(|item| item.2).collect_vec();
|
||||
let names_types = indices
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|item| (item.1, item.2))
|
||||
.collect_vec();
|
||||
|
||||
if !indices.is_empty() {
|
||||
term = builder::list_access_to_uplc(
|
||||
&names,
|
||||
&id_list,
|
||||
false,
|
||||
current_index,
|
||||
term,
|
||||
inner_types,
|
||||
check_last_item,
|
||||
false,
|
||||
self.tracing,
|
||||
);
|
||||
|
||||
term = term.apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(value));
|
||||
|
||||
arg_stack.push(term);
|
||||
} else if check_last_item {
|
||||
let trace_term = if self.tracing {
|
||||
Term::Error.trace(Term::string("Expected no fields for Constr"))
|
||||
let error_term = if self.tracing {
|
||||
Term::Error.trace(Term::var(
|
||||
self.special_functions.use_function(TOO_MANY_ITEMS),
|
||||
))
|
||||
} else {
|
||||
Term::Error
|
||||
};
|
||||
|
||||
term = Term::var(CONSTR_FIELDS_EXPOSER)
|
||||
term = builder::list_access_to_uplc(
|
||||
&names_types,
|
||||
&id_list,
|
||||
false,
|
||||
current_index,
|
||||
term,
|
||||
check_last_item,
|
||||
false,
|
||||
error_term,
|
||||
);
|
||||
|
||||
term = term.apply(
|
||||
Term::var(self.special_functions.use_function(CONSTR_FIELDS_EXPOSER))
|
||||
.apply(value),
|
||||
);
|
||||
|
||||
arg_stack.push(term);
|
||||
} else if check_last_item {
|
||||
let trace_term = if self.tracing {
|
||||
Term::Error.trace(Term::var(
|
||||
self.special_functions.use_function(CONSTR_NOT_EMPTY),
|
||||
))
|
||||
} else {
|
||||
Term::Error
|
||||
};
|
||||
|
||||
term = Term::var(self.special_functions.use_function(CONSTR_FIELDS_EXPOSER))
|
||||
.apply(value)
|
||||
.delayed_choose_list(term, trace_term);
|
||||
|
||||
|
@ -4772,18 +4812,18 @@ impl<'a> CodeGenerator<'a> {
|
|||
};
|
||||
}
|
||||
Air::FieldsEmpty => {
|
||||
self.needs_field_access = true;
|
||||
|
||||
let value = arg_stack.pop().unwrap();
|
||||
let mut term = arg_stack.pop().unwrap();
|
||||
|
||||
let trace_term = if self.tracing {
|
||||
Term::Error.trace(Term::string("Expected no fields for Constr"))
|
||||
Term::Error.trace(Term::var(
|
||||
self.special_functions.use_function(CONSTR_NOT_EMPTY),
|
||||
))
|
||||
} else {
|
||||
Term::Error
|
||||
};
|
||||
|
||||
term = Term::var(CONSTR_FIELDS_EXPOSER)
|
||||
term = Term::var(self.special_functions.use_function(CONSTR_FIELDS_EXPOSER))
|
||||
.apply(value)
|
||||
.delayed_choose_list(term, trace_term);
|
||||
|
||||
|
@ -4794,7 +4834,9 @@ impl<'a> CodeGenerator<'a> {
|
|||
let mut term = arg_stack.pop().unwrap();
|
||||
|
||||
let trace_term = if self.tracing {
|
||||
Term::Error.trace(Term::string("Expected no items for List"))
|
||||
Term::Error.trace(Term::var(
|
||||
self.special_functions.use_function(LIST_NOT_EMPTY),
|
||||
))
|
||||
} else {
|
||||
Term::Error
|
||||
};
|
||||
|
@ -4867,7 +4909,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
indices,
|
||||
tipo,
|
||||
} => {
|
||||
self.needs_field_access = true;
|
||||
let tail_name_prefix = "__tail_index";
|
||||
|
||||
let data_type = lookup_data_type_by_tipo(&self.data_types, &tipo)
|
||||
|
@ -4946,9 +4987,10 @@ impl<'a> CodeGenerator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
term = term
|
||||
.lambda(format!("{tail_name_prefix}_0"))
|
||||
.apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(record));
|
||||
term = term.lambda(format!("{tail_name_prefix}_0")).apply(
|
||||
Term::var(self.special_functions.use_function(CONSTR_FIELDS_EXPOSER))
|
||||
.apply(record),
|
||||
);
|
||||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
|
@ -5018,16 +5060,25 @@ impl<'a> CodeGenerator<'a> {
|
|||
id_list.push(self.id_gen.next());
|
||||
}
|
||||
|
||||
let names_types = names.into_iter().zip(inner_types).collect_vec();
|
||||
|
||||
let error_term = if self.tracing {
|
||||
Term::Error.trace(Term::var(
|
||||
self.special_functions.use_function(TOO_MANY_ITEMS),
|
||||
))
|
||||
} else {
|
||||
Term::Error
|
||||
};
|
||||
|
||||
term = builder::list_access_to_uplc(
|
||||
&names,
|
||||
&names_types,
|
||||
&id_list,
|
||||
false,
|
||||
0,
|
||||
term,
|
||||
tipo.get_inner_types(),
|
||||
check_last_item,
|
||||
false,
|
||||
self.tracing,
|
||||
error_term,
|
||||
)
|
||||
.apply(value);
|
||||
|
||||
|
|
|
@ -36,6 +36,13 @@ pub type Params = Vec<String>;
|
|||
|
||||
pub type CycleFunctionNames = Vec<String>;
|
||||
|
||||
pub const TOO_MANY_ITEMS: &str = "TOO_MANY_ITEMS";
|
||||
pub const LIST_NOT_EMPTY: &str = "LIST_NOT_EMPTY";
|
||||
pub const CONSTR_NOT_EMPTY: &str = "CONSTR_NOT_EMPTY";
|
||||
pub const INCORRECT_BOOLEAN: &str = "INCORRECT_BOOLEAN";
|
||||
pub const INCORRECT_CONSTR: &str = "INCORRECT_CONSTR";
|
||||
pub const CONSTR_INDEX_MISMATCH: &str = "CONSTR_INDEX_MISMATCH";
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum CodeGenFunction {
|
||||
Function { body: AirTree, params: Params },
|
||||
|
@ -181,6 +188,91 @@ impl ClauseProperties {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CodeGenSpecialFuncs {
|
||||
pub used_funcs: Vec<String>,
|
||||
pub key_to_func: IndexMap<String, Term<Name>>,
|
||||
}
|
||||
|
||||
impl CodeGenSpecialFuncs {
|
||||
pub fn new() -> Self {
|
||||
let mut key_to_func = IndexMap::new();
|
||||
|
||||
key_to_func.insert(
|
||||
CONSTR_FIELDS_EXPOSER.to_string(),
|
||||
Term::snd_pair()
|
||||
.apply(Term::unconstr_data().apply(Term::var("__constr_var")))
|
||||
.lambda("__constr_var"),
|
||||
);
|
||||
|
||||
key_to_func.insert(
|
||||
CONSTR_INDEX_EXPOSER.to_string(),
|
||||
Term::fst_pair()
|
||||
.apply(Term::unconstr_data().apply(Term::var("__constr_var")))
|
||||
.lambda("__constr_var"),
|
||||
);
|
||||
|
||||
key_to_func.insert(
|
||||
TOO_MANY_ITEMS.to_string(),
|
||||
Term::string("List/Tuple/Constr contains more items than expected"),
|
||||
);
|
||||
|
||||
key_to_func.insert(
|
||||
LIST_NOT_EMPTY.to_string(),
|
||||
Term::string("Expected no items for List"),
|
||||
);
|
||||
|
||||
key_to_func.insert(
|
||||
CONSTR_NOT_EMPTY.to_string(),
|
||||
Term::string("Expected no fields for Constr"),
|
||||
);
|
||||
|
||||
key_to_func.insert(
|
||||
INCORRECT_BOOLEAN.to_string(),
|
||||
Term::string("Expected on incorrect Boolean variant"),
|
||||
);
|
||||
|
||||
key_to_func.insert(
|
||||
INCORRECT_CONSTR.to_string(),
|
||||
Term::string("Expected on incorrect Constr variant"),
|
||||
);
|
||||
|
||||
key_to_func.insert(
|
||||
CONSTR_INDEX_MISMATCH.to_string(),
|
||||
Term::string("Constr index didn't match a type variant"),
|
||||
);
|
||||
|
||||
CodeGenSpecialFuncs {
|
||||
used_funcs: vec![],
|
||||
key_to_func,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn use_function(&mut self, func_name: &'static str) -> &'static str {
|
||||
if !self.used_funcs.contains(&func_name.to_string()) {
|
||||
self.used_funcs.push(func_name.to_string());
|
||||
}
|
||||
func_name
|
||||
}
|
||||
|
||||
pub fn get_function(&self, func_name: &String) -> Term<Name> {
|
||||
self.key_to_func[func_name].clone()
|
||||
}
|
||||
|
||||
pub fn apply_used_functions(&self, mut term: Term<Name>) -> Term<Name> {
|
||||
for func_name in self.used_funcs.iter() {
|
||||
term = term.lambda(func_name).apply(self.get_function(func_name));
|
||||
}
|
||||
term
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CodeGenSpecialFuncs {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_generic_id_and_type(tipo: &Type, param: &Type) -> Vec<(u64, Rc<Type>)> {
|
||||
let mut generics_ids = vec![];
|
||||
|
||||
|
@ -1265,27 +1357,16 @@ pub fn convert_type_to_data(term: Term<Name>, field_type: &Rc<Type>) -> Term<Nam
|
|||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn list_access_to_uplc(
|
||||
names: &[String],
|
||||
names_types: &[(String, Rc<Type>)],
|
||||
id_list: &[u64],
|
||||
tail: bool,
|
||||
current_index: usize,
|
||||
term: Term<Name>,
|
||||
tipos: Vec<Rc<Type>>,
|
||||
check_last_item: bool,
|
||||
is_list_accessor: bool,
|
||||
tracing: bool,
|
||||
error_term: Term<Name>,
|
||||
) -> Term<Name> {
|
||||
let trace_term = if tracing {
|
||||
Term::Error.trace(Term::string(
|
||||
"List/Tuple/Constr contains more items than expected",
|
||||
))
|
||||
} else {
|
||||
Term::Error
|
||||
};
|
||||
|
||||
if let Some((first, names)) = names.split_first() {
|
||||
let (current_tipo, tipos) = tipos.split_first().unwrap();
|
||||
|
||||
if let Some(((first, current_tipo), names_types)) = names_types.split_first() {
|
||||
let head_list =
|
||||
if matches!(current_tipo.get_uplc_type(), UplcType::Pair(_, _)) && is_list_accessor {
|
||||
Term::head_list().apply(Term::var(format!(
|
||||
|
@ -1302,11 +1383,11 @@ pub fn list_access_to_uplc(
|
|||
)
|
||||
};
|
||||
|
||||
if names.len() == 1 && tail {
|
||||
if first == "_" && names[0] == "_" {
|
||||
if names_types.len() == 1 && tail {
|
||||
if first == "_" && names_types[0].0 == "_" {
|
||||
term.lambda("_")
|
||||
} else if first == "_" {
|
||||
term.lambda(names[0].clone())
|
||||
term.lambda(&names_types[0].0)
|
||||
.apply(Term::tail_list().apply(Term::var(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
|
@ -1315,25 +1396,25 @@ pub fn list_access_to_uplc(
|
|||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))
|
||||
} else if names[0] == "_" {
|
||||
term.lambda(first.clone()).apply(head_list).lambda(format!(
|
||||
} else if names_types[0].0 == "_" {
|
||||
term.lambda(first).apply(head_list).lambda(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))
|
||||
} else {
|
||||
term.lambda(names[0].clone())
|
||||
term.lambda(&names_types[0].0)
|
||||
.apply(Term::tail_list().apply(Term::var(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))))
|
||||
.lambda(first.clone())
|
||||
.lambda(first)
|
||||
.apply(head_list)
|
||||
.lambda(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))
|
||||
}
|
||||
} else if names.is_empty() {
|
||||
} else if names_types.is_empty() {
|
||||
if first == "_" {
|
||||
if check_last_item {
|
||||
Term::tail_list()
|
||||
|
@ -1341,7 +1422,7 @@ pub fn list_access_to_uplc(
|
|||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
)))
|
||||
.delayed_choose_list(term, trace_term)
|
||||
.delayed_choose_list(term, error_term)
|
||||
} else {
|
||||
term
|
||||
}
|
||||
|
@ -1357,7 +1438,7 @@ pub fn list_access_to_uplc(
|
|||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
)))
|
||||
.delayed_choose_list(term, trace_term)
|
||||
.delayed_choose_list(term, error_term)
|
||||
} else {
|
||||
term
|
||||
}
|
||||
|
@ -1370,15 +1451,14 @@ pub fn list_access_to_uplc(
|
|||
}
|
||||
} else if first == "_" {
|
||||
let mut list_access_inner = list_access_to_uplc(
|
||||
names,
|
||||
names_types,
|
||||
id_list,
|
||||
tail,
|
||||
current_index + 1,
|
||||
term,
|
||||
tipos.to_owned(),
|
||||
check_last_item,
|
||||
is_list_accessor,
|
||||
tracing,
|
||||
error_term,
|
||||
);
|
||||
|
||||
list_access_inner = match &list_access_inner {
|
||||
|
@ -1409,15 +1489,14 @@ pub fn list_access_to_uplc(
|
|||
}
|
||||
} else {
|
||||
let mut list_access_inner = list_access_to_uplc(
|
||||
names,
|
||||
names_types,
|
||||
id_list,
|
||||
tail,
|
||||
current_index + 1,
|
||||
term,
|
||||
tipos.to_owned(),
|
||||
check_last_item,
|
||||
is_list_accessor,
|
||||
tracing,
|
||||
error_term,
|
||||
);
|
||||
|
||||
list_access_inner = match &list_access_inner {
|
||||
|
|
Loading…
Reference in New Issue