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