feat: Remove tuple_index and record_access in favor of faster more direct functions for
accessing an item in a tuple or a field in a record
This commit is contained in:
@@ -10,7 +10,7 @@ use indexmap::{IndexMap, IndexSet};
|
||||
use itertools::Itertools;
|
||||
use uplc::{
|
||||
ast::{Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType},
|
||||
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, CONSTR_INDEX_EXPOSER, EXPECT_ON_LIST},
|
||||
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER, EXPECT_ON_LIST},
|
||||
builtins::DefaultFunction,
|
||||
machine::cost_model::ExBudget,
|
||||
optimize::aiken_optimize_and_intern,
|
||||
@@ -22,7 +22,7 @@ use crate::{
|
||||
AssignmentKind, BinOp, Pattern, Span, TypedArg, TypedClause, TypedDataType, TypedFunction,
|
||||
TypedPattern, TypedValidator, UnOp,
|
||||
},
|
||||
builtins::{bool, data, int, void},
|
||||
builtins::{bool, data, int, list, void},
|
||||
expr::TypedExpr,
|
||||
gen_uplc::builder::{
|
||||
check_replaceable_opaque_type, convert_opaque_type, erase_opaque_type_operations,
|
||||
@@ -187,10 +187,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
fn finalize(&mut self, mut term: Term<Name>) -> Program<Name> {
|
||||
if self.needs_field_access {
|
||||
term = term
|
||||
.constr_get_field()
|
||||
.constr_fields_exposer()
|
||||
.constr_index_exposer();
|
||||
term = term.constr_fields_exposer().constr_index_exposer();
|
||||
}
|
||||
|
||||
// TODO: Once SOP is implemented, new version is 1.1.0
|
||||
@@ -550,7 +547,38 @@ impl<'a> CodeGenerator<'a> {
|
||||
if check_replaceable_opaque_type(&record.tipo(), &self.data_types) {
|
||||
self.build(record)
|
||||
} else {
|
||||
AirTree::record_access(*index, tipo.clone(), self.build(record))
|
||||
self.needs_field_access = true;
|
||||
let function_name = format!("__access_index_{}", *index);
|
||||
|
||||
if self.code_gen_functions.get(&function_name).is_none() {
|
||||
let mut body = AirTree::local_var("__fields", list(data()));
|
||||
|
||||
for _ in 0..*index {
|
||||
body = AirTree::builtin(
|
||||
DefaultFunction::TailList,
|
||||
list(data()),
|
||||
vec![body],
|
||||
)
|
||||
}
|
||||
|
||||
body = AirTree::builtin(DefaultFunction::HeadList, data(), vec![body]);
|
||||
|
||||
self.code_gen_functions.insert(
|
||||
function_name.clone(),
|
||||
CodeGenFunction::Function {
|
||||
body,
|
||||
params: vec!["__fields".to_string()],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let list_of_fields = AirTree::call(
|
||||
AirTree::local_var(CONSTR_FIELDS_EXPOSER, void()),
|
||||
list(data()),
|
||||
vec![self.build(record)],
|
||||
);
|
||||
|
||||
AirTree::index_access(function_name, tipo.clone(), list_of_fields)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,8 +650,38 @@ impl<'a> CodeGenerator<'a> {
|
||||
tipo.clone(),
|
||||
),
|
||||
|
||||
TypedExpr::TupleIndex { index, tuple, .. } => {
|
||||
AirTree::tuple_index(*index, tuple.tipo(), self.build(tuple))
|
||||
TypedExpr::TupleIndex {
|
||||
index, tuple, tipo, ..
|
||||
} => {
|
||||
if tuple.tipo().is_2_tuple() {
|
||||
AirTree::pair_index(*index, tipo.clone(), self.build(tuple))
|
||||
} else {
|
||||
let function_name = format!("__access_index_{}", *index);
|
||||
|
||||
if self.code_gen_functions.get(&function_name).is_none() {
|
||||
let mut body = AirTree::local_var("__fields", list(data()));
|
||||
|
||||
for _ in 0..*index {
|
||||
body = AirTree::builtin(
|
||||
DefaultFunction::TailList,
|
||||
list(data()),
|
||||
vec![body],
|
||||
)
|
||||
}
|
||||
|
||||
body = AirTree::builtin(DefaultFunction::HeadList, data(), vec![body]);
|
||||
|
||||
self.code_gen_functions.insert(
|
||||
function_name.clone(),
|
||||
CodeGenFunction::Function {
|
||||
body,
|
||||
params: vec!["__fields".to_string()],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
AirTree::index_access(function_name, tipo.clone(), self.build(tuple))
|
||||
}
|
||||
}
|
||||
|
||||
TypedExpr::ErrorTerm { tipo, .. } => AirTree::error(tipo.clone()),
|
||||
@@ -3876,10 +3934,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
) {
|
||||
let mut term = self.uplc_code_gen(air_vec.clone());
|
||||
|
||||
term = term
|
||||
.constr_get_field()
|
||||
.constr_fields_exposer()
|
||||
.constr_index_exposer();
|
||||
term = term.constr_fields_exposer().constr_index_exposer();
|
||||
|
||||
let mut program: Program<Name> = Program {
|
||||
version: (1, 0, 0),
|
||||
@@ -4660,18 +4715,6 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
Air::RecordAccess { record_index, tipo } => {
|
||||
self.needs_field_access = true;
|
||||
let constr = arg_stack.pop().unwrap();
|
||||
|
||||
let mut term = Term::var(CONSTR_GET_FIELD)
|
||||
.apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(constr))
|
||||
.apply(Term::integer(record_index.into()));
|
||||
|
||||
term = builder::convert_data_to_type(term, &tipo);
|
||||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
Air::FieldsExpose {
|
||||
indices,
|
||||
check_last_item,
|
||||
@@ -4931,33 +4974,6 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
Air::TupleIndex { tipo, tuple_index } => {
|
||||
let mut term = arg_stack.pop().unwrap();
|
||||
|
||||
if matches!(tipo.get_uplc_type(), UplcType::Pair(_, _)) {
|
||||
if tuple_index == 0 {
|
||||
term = builder::convert_data_to_type(
|
||||
Term::fst_pair().apply(term),
|
||||
&tipo.get_inner_types()[0],
|
||||
);
|
||||
} else {
|
||||
term = builder::convert_data_to_type(
|
||||
Term::snd_pair().apply(term),
|
||||
&tipo.get_inner_types()[1],
|
||||
);
|
||||
}
|
||||
} else {
|
||||
self.needs_field_access = true;
|
||||
term = builder::convert_data_to_type(
|
||||
Term::var(CONSTR_GET_FIELD)
|
||||
.apply(term)
|
||||
.apply(Term::integer(tuple_index.into())),
|
||||
&tipo.get_inner_types()[tuple_index],
|
||||
);
|
||||
}
|
||||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
Air::TupleAccessor {
|
||||
tipo,
|
||||
names,
|
||||
|
||||
@@ -147,10 +147,6 @@ pub enum Air {
|
||||
tipo: Rc<Type>,
|
||||
},
|
||||
// Field Access
|
||||
RecordAccess {
|
||||
record_index: u64,
|
||||
tipo: Rc<Type>,
|
||||
},
|
||||
FieldsExpose {
|
||||
indices: Vec<(usize, String, Rc<Type>)>,
|
||||
check_last_item: bool,
|
||||
@@ -173,10 +169,6 @@ pub enum Air {
|
||||
tipo: Rc<Type>,
|
||||
check_last_item: bool,
|
||||
},
|
||||
TupleIndex {
|
||||
tipo: Rc<Type>,
|
||||
tuple_index: usize,
|
||||
},
|
||||
// Misc.
|
||||
ErrorTerm {
|
||||
tipo: Rc<Type>,
|
||||
|
||||
@@ -315,18 +315,6 @@ pub enum AirExpression {
|
||||
record: Box<AirTree>,
|
||||
args: Vec<AirTree>,
|
||||
},
|
||||
// Field Access
|
||||
RecordAccess {
|
||||
field_index: u64,
|
||||
tipo: Rc<Type>,
|
||||
record: Box<AirTree>,
|
||||
},
|
||||
// Tuple Access
|
||||
TupleIndex {
|
||||
tipo: Rc<Type>,
|
||||
tuple_index: usize,
|
||||
tuple: Box<AirTree>,
|
||||
},
|
||||
// Misc.
|
||||
ErrorTerm {
|
||||
tipo: Rc<Type>,
|
||||
@@ -684,12 +672,33 @@ impl AirTree {
|
||||
args,
|
||||
})
|
||||
}
|
||||
pub fn record_access(field_index: u64, tipo: Rc<Type>, record: AirTree) -> AirTree {
|
||||
AirTree::Expression(AirExpression::RecordAccess {
|
||||
field_index,
|
||||
tipo,
|
||||
record: record.into(),
|
||||
})
|
||||
pub fn index_access(function_name: String, tipo: Rc<Type>, list_of_fields: AirTree) -> AirTree {
|
||||
AirTree::cast_from_data(
|
||||
AirTree::call(
|
||||
AirTree::var(
|
||||
ValueConstructor::public(
|
||||
Type::Fn {
|
||||
args: vec![list(data())],
|
||||
ret: data(),
|
||||
}
|
||||
.into(),
|
||||
ValueConstructorVariant::ModuleFn {
|
||||
name: function_name.clone(),
|
||||
field_map: None,
|
||||
module: "".to_string(),
|
||||
arity: 1,
|
||||
location: Span::empty(),
|
||||
builtin: None,
|
||||
},
|
||||
),
|
||||
function_name,
|
||||
"",
|
||||
),
|
||||
data(),
|
||||
vec![list_of_fields],
|
||||
),
|
||||
tipo.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn fields_expose(
|
||||
@@ -754,12 +763,19 @@ impl AirTree {
|
||||
hoisted_over: None,
|
||||
}
|
||||
}
|
||||
pub fn tuple_index(tuple_index: usize, tipo: Rc<Type>, tuple: AirTree) -> AirTree {
|
||||
AirTree::Expression(AirExpression::TupleIndex {
|
||||
tipo,
|
||||
tuple_index,
|
||||
tuple: tuple.into(),
|
||||
})
|
||||
pub fn pair_index(index: usize, tipo: Rc<Type>, tuple: AirTree) -> AirTree {
|
||||
AirTree::cast_from_data(
|
||||
AirTree::builtin(
|
||||
if index == 0 {
|
||||
DefaultFunction::FstPair
|
||||
} else {
|
||||
DefaultFunction::SndPair
|
||||
},
|
||||
data(),
|
||||
vec![tuple],
|
||||
),
|
||||
tipo.clone(),
|
||||
)
|
||||
}
|
||||
pub fn error(tipo: Rc<Type>) -> AirTree {
|
||||
AirTree::Expression(AirExpression::ErrorTerm { tipo })
|
||||
@@ -1241,28 +1257,6 @@ impl AirTree {
|
||||
arg.create_air_vec(air_vec);
|
||||
}
|
||||
}
|
||||
AirExpression::RecordAccess {
|
||||
field_index,
|
||||
tipo,
|
||||
record,
|
||||
} => {
|
||||
air_vec.push(Air::RecordAccess {
|
||||
record_index: *field_index,
|
||||
tipo: tipo.clone(),
|
||||
});
|
||||
record.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::TupleIndex {
|
||||
tipo,
|
||||
tuple_index,
|
||||
tuple,
|
||||
} => {
|
||||
air_vec.push(Air::TupleIndex {
|
||||
tipo: tipo.clone(),
|
||||
tuple_index: *tuple_index,
|
||||
});
|
||||
tuple.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::ErrorTerm { tipo } => {
|
||||
air_vec.push(Air::ErrorTerm { tipo: tipo.clone() })
|
||||
}
|
||||
@@ -1300,8 +1294,6 @@ impl AirTree {
|
||||
| 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(),
|
||||
@@ -1351,9 +1343,7 @@ impl AirTree {
|
||||
| AirExpression::CastFromData { tipo, .. }
|
||||
| AirExpression::CastToData { tipo, .. }
|
||||
| AirExpression::If { tipo, .. }
|
||||
| AirExpression::RecordAccess { tipo, .. }
|
||||
| AirExpression::Constr { tipo, .. }
|
||||
| AirExpression::TupleIndex { tipo, .. }
|
||||
| AirExpression::ErrorTerm { tipo }
|
||||
| AirExpression::Trace { tipo, .. } => vec![tipo],
|
||||
AirExpression::Var { constructor, .. } => {
|
||||
@@ -1836,24 +1826,6 @@ impl AirTree {
|
||||
);
|
||||
}
|
||||
}
|
||||
AirExpression::RecordAccess { record, .. } => {
|
||||
record.do_traverse_tree_with(
|
||||
tree_path,
|
||||
current_depth + 1,
|
||||
index_count.next_number(),
|
||||
with,
|
||||
apply_with_func_last,
|
||||
);
|
||||
}
|
||||
AirExpression::TupleIndex { tuple, .. } => {
|
||||
tuple.do_traverse_tree_with(
|
||||
tree_path,
|
||||
current_depth + 1,
|
||||
index_count.next_number(),
|
||||
with,
|
||||
apply_with_func_last,
|
||||
);
|
||||
}
|
||||
AirExpression::Trace { msg, then, .. } => {
|
||||
msg.do_traverse_tree_with(
|
||||
tree_path,
|
||||
@@ -2170,21 +2142,6 @@ impl AirTree {
|
||||
|
||||
item.do_find_air_tree_node(tree_path_iter)
|
||||
}
|
||||
AirExpression::RecordAccess { record, .. } => {
|
||||
if *index == 0 {
|
||||
record.as_mut().do_find_air_tree_node(tree_path_iter)
|
||||
} else {
|
||||
panic!("Tree Path index outside tree children nodes")
|
||||
}
|
||||
}
|
||||
AirExpression::TupleIndex { tuple, .. } => {
|
||||
if *index == 0 {
|
||||
tuple.as_mut().do_find_air_tree_node(tree_path_iter)
|
||||
} else {
|
||||
panic!("Tree Path index outside tree children nodes")
|
||||
}
|
||||
}
|
||||
|
||||
AirExpression::Trace { msg, then, .. } => {
|
||||
if *index == 0 {
|
||||
msg.as_mut().do_find_air_tree_node(tree_path_iter)
|
||||
|
||||
Reference in New Issue
Block a user