fix: Various fixes for FieldsExpose, ListAccessor, TupleAccessor

This commit is contained in:
Kasey White 2023-02-07 17:42:33 -05:00 committed by Lucas
parent cf7a20b986
commit 986a6009f7
6 changed files with 135 additions and 136 deletions

View File

@ -510,11 +510,14 @@ pub fn list_access_to_uplc(
term: Term<Name>, term: Term<Name>,
tipos: Vec<Arc<Type>>, tipos: Vec<Arc<Type>>,
check_last_item: bool, check_last_item: bool,
is_list_accessor: bool,
) -> Term<Name> { ) -> Term<Name> {
if let Some((first, names)) = names.split_first() { if let Some((first, names)) = names.split_first() {
let (current_tipo, tipos) = tipos.split_first().unwrap(); let (current_tipo, tipos) = tipos.split_first().unwrap();
let head_list = if current_tipo.is_map() { let head_list = if matches!(current_tipo.get_uplc_type(), UplcType::Pair(_, _))
&& is_list_accessor
{
apply_wrap( apply_wrap(
Term::Builtin(DefaultFunction::HeadList).force_wrap(), Term::Builtin(DefaultFunction::HeadList).force_wrap(),
Term::Var( Term::Var(
@ -622,7 +625,7 @@ pub fn list_access_to_uplc(
Term::Builtin(DefaultFunction::Trace).force_wrap(), Term::Builtin(DefaultFunction::Trace).force_wrap(),
Term::Constant( Term::Constant(
UplcConstant::String( UplcConstant::String(
"List/Tuple contains more items than it should" "List/Tuple/Constr contains more items than it should"
.to_string(), .to_string(),
) )
.into(), .into(),
@ -664,6 +667,7 @@ pub fn list_access_to_uplc(
term, term,
tipos.to_owned(), tipos.to_owned(),
check_last_item, check_last_item,
is_list_accessor,
), ),
apply_wrap( apply_wrap(
Term::Builtin(DefaultFunction::TailList).force_wrap(), Term::Builtin(DefaultFunction::TailList).force_wrap(),
@ -757,7 +761,9 @@ pub fn check_when_pattern_needs(
check_when_pattern_needs(&argument.value, clause_properties); check_when_pattern_needs(&argument.value, clause_properties);
} }
} }
Pattern::Discard { .. } => {} Pattern::Discard { .. } => {
*clause_properties.needs_constr_var() = true;
}
_ => todo!("{pattern:#?}"), _ => todo!("{pattern:#?}"),
} }
} }

View File

@ -354,7 +354,7 @@ impl<'a> CodeGenerator<'a> {
self.build_ir(&clauses[0].then, &mut value_vec, scope.clone()); self.build_ir(&clauses[0].then, &mut value_vec, scope.clone());
self.build_ir(&subject, &mut value_vec, scope.clone()); self.build_ir(&subject, &mut subject_vec, scope.clone());
self.assignment_ir( self.assignment_ir(
&clauses[0].pattern[0], &clauses[0].pattern[0],
@ -1192,7 +1192,10 @@ impl<'a> CodeGenerator<'a> {
scope.clone(), scope.clone(),
); );
var_name.map(|var_name| (label, var_name, *field_index)) var_name.map_or(
Some((label.clone(), "_".to_string(), *field_index)),
|var_name| Some((label, var_name, *field_index)),
)
}) })
.sorted_by(|item1, item2| item1.2.cmp(&item2.2)) .sorted_by(|item1, item2| item1.2.cmp(&item2.2))
.collect::<Vec<(String, String, usize)>>(); .collect::<Vec<(String, String, usize)>>();
@ -1230,7 +1233,9 @@ impl<'a> CodeGenerator<'a> {
scope.clone(), scope.clone(),
); );
var_name.map(|var_name| (var_name, index)) var_name.map_or(Some(("_".to_string(), index)), |var_name| {
Some((var_name, index))
})
}) })
.collect::<Vec<(String, usize)>>(); .collect::<Vec<(String, usize)>>();
@ -1788,7 +1793,7 @@ impl<'a> CodeGenerator<'a> {
.filter_map(|(index, item)| { .filter_map(|(index, item)| {
let label = item.label.clone().unwrap_or_default(); let label = item.label.clone().unwrap_or_default();
let field_index = if let Some(field_map) = &field_map { let field_index = if let Some(field_map) = &field_map {
*field_map.fields.get(&label).map(|x| &x.0).unwrap() *field_map.fields.get(&label).map(|x| &x.0).unwrap_or(&index)
} else { } else {
index index
}; };
@ -1800,6 +1805,7 @@ impl<'a> CodeGenerator<'a> {
&assignment_properties, &assignment_properties,
&scope, &scope,
) )
.map_or(Some(("_".to_string(), index)), Some)
}) })
.sorted_by(|item1, item2| item1.1.cmp(&item2.1)) .sorted_by(|item1, item2| item1.1.cmp(&item2.1))
.collect::<Vec<(String, usize)>>(); .collect::<Vec<(String, usize)>>();
@ -1852,14 +1858,25 @@ impl<'a> CodeGenerator<'a> {
.collect::<Vec<(String, usize)>>(); .collect::<Vec<(String, usize)>>();
if !arguments_index.is_empty() { if !arguments_index.is_empty() {
let mut current_index = 0;
let mut final_args = vec![];
for index in 0..elems.len() {
if arguments_index.get(current_index).is_some()
&& arguments_index[current_index].1 == index
{
final_args.push(arguments_index.get(current_index).unwrap().clone());
current_index += 1;
} else {
final_args.push(("_".to_string(), index));
}
}
pattern_vec.push(Air::TupleAccessor { pattern_vec.push(Air::TupleAccessor {
scope, scope,
names: arguments_index names: final_args.into_iter().map(|(item, _)| item).collect_vec(),
.into_iter()
.map(|(item, _)| item)
.collect_vec(),
tipo: tipo.clone().into(), tipo: tipo.clone().into(),
check_last_item: true, check_last_item: false,
}); });
} else { } else {
pattern_vec.push(Air::Let { pattern_vec.push(Air::Let {
@ -2109,7 +2126,7 @@ impl<'a> CodeGenerator<'a> {
if arguments_index.get(current_index).is_some() if arguments_index.get(current_index).is_some()
&& arguments_index[current_index].1 == index && arguments_index[current_index].1 == index
{ {
final_args.push(arguments_index.get(index).unwrap().clone()); final_args.push(arguments_index.get(current_index).unwrap().clone());
current_index += 1; current_index += 1;
} else { } else {
let id_next = self.id_gen.next(); let id_next = self.id_gen.next();
@ -3826,6 +3843,7 @@ impl<'a> CodeGenerator<'a> {
term, term,
inner_types, inner_types,
check_last_item, check_last_item,
true,
), ),
apply_wrap( apply_wrap(
Term::Builtin(DefaultFunction::TailList).force_wrap(), Term::Builtin(DefaultFunction::TailList).force_wrap(),
@ -5083,76 +5101,34 @@ impl<'a> CodeGenerator<'a> {
let mut term = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap();
let list_id = self.id_gen.next(); let list_id = self.id_gen.next();
id_list.push(list_id);
for _ in 0..indices.len() { for _ in 0..indices.len() {
id_list.push(self.id_gen.next()); id_list.push(self.id_gen.next());
} }
let current_index = 0; let current_index = 0;
let (first_name, indices) = indices.split_first().unwrap();
let head_list = convert_data_to_type(
apply_wrap(
Term::Builtin(DefaultFunction::HeadList).force_wrap(),
Term::Var(
Name {
text: format!("__constr_fields_{list_id}"),
unique: 0.into(),
}
.into(),
),
),
&first_name.2,
);
let names = indices.iter().cloned().map(|item| item.1).collect_vec(); let names = indices.iter().cloned().map(|item| item.1).collect_vec();
let inner_types = indices.iter().cloned().map(|item| item.2).collect_vec(); let inner_types = indices.iter().cloned().map(|item| item.2).collect_vec();
let tail_list = if !indices.is_empty() { term = if !indices.is_empty() {
apply_wrap( list_access_to_uplc(
list_access_to_uplc( &names,
&names, &id_list,
&id_list, false,
false, current_index,
current_index, term,
term, inner_types,
inner_types, check_last_item,
check_last_item, false,
),
apply_wrap(
Term::Builtin(DefaultFunction::TailList).force_wrap(),
Term::Var(
Name {
text: format!("__constr_fields_{list_id}"),
unique: 0.into(),
}
.into(),
),
),
) )
} else { } else {
term term
}; };
term = apply_wrap( term = apply_wrap(
Term::Lambda { term,
parameter_name: Name {
text: format!("__constr_fields_{list_id}"),
unique: 0.into(),
}
.into(),
body: apply_wrap(
Term::Lambda {
parameter_name: Name {
text: first_name.1.clone(),
unique: 0.into(),
}
.into(),
body: tail_list.into(),
},
head_list,
)
.into(),
},
apply_wrap( apply_wrap(
Term::Var( Term::Var(
Name { Name {
@ -5557,69 +5533,23 @@ impl<'a> CodeGenerator<'a> {
); );
} else { } else {
let mut id_list = vec![]; let mut id_list = vec![];
id_list.push(list_id);
for _ in 0..names.len() { for _ in 0..names.len() {
id_list.push(self.id_gen.next()); id_list.push(self.id_gen.next());
} }
let current_index = 0;
let (first_name, names) = names.split_first().unwrap();
let head_list = convert_data_to_type(
apply_wrap(
Term::Builtin(DefaultFunction::HeadList).force_wrap(),
Term::Var(
Name {
text: format!("__tuple_{list_id}"),
unique: 0.into(),
}
.into(),
),
),
&tipo.get_inner_types()[0],
);
term = apply_wrap( term = apply_wrap(
Term::Lambda { list_access_to_uplc(
parameter_name: Name { &names,
text: format!("__tuple_{list_id}"), &id_list,
unique: 0.into(), false,
} 0,
.into(), term,
body: apply_wrap( tipo.get_inner_types(),
Term::Lambda { check_last_item,
parameter_name: Name { false,
text: first_name.clone(), ),
unique: 0.into(),
}
.into(),
body: apply_wrap(
list_access_to_uplc(
names,
&id_list,
false,
current_index,
term,
tipo.get_inner_types(),
check_last_item,
),
apply_wrap(
Term::Builtin(DefaultFunction::TailList).force_wrap(),
Term::Var(
Name {
text: format!("__tuple_{list_id}"),
unique: 0.into(),
}
.into(),
),
),
)
.into(),
},
head_list,
)
.into(),
},
value, value,
); );
} }

View File

@ -142,17 +142,31 @@ fn inline_basic_reduce(term: &mut Term<Name>) {
body, body,
} = func } = func
{ {
if let replace_term @ (Term::Var(_) let mut occurrences = 0;
| Term::Constant(_) var_occurrences(body, parameter_name.clone(), &mut occurrences);
| Term::Error if occurrences == 1 {
| Term::Delay(_) if let replace_term @ (Term::Var(_)
| Term::Lambda { .. }) = argument.as_ref() | Term::Constant(_)
{ | Term::Error
let mut occurrences = 0; | Term::Delay(_)
var_occurrences(body, parameter_name.clone(), &mut occurrences); | Term::Lambda { .. }) = argument.as_ref()
if occurrences <= 1 { {
*term = if occurrences == 1 {
substitute_term(body.as_ref(), parameter_name.clone(), replace_term); *term = substitute_term(
body.as_ref(),
parameter_name.clone(),
replace_term,
);
}
}
} else if occurrences == 0 {
error_occurrences(argument.as_ref(), &mut occurrences);
if occurrences == 0 {
*term = substitute_term(
body.as_ref(),
parameter_name.clone(),
argument.as_ref(),
);
} }
} }
} }
@ -194,6 +208,28 @@ fn var_occurrences(term: &Term<Name>, search_for: Rc<Name>, occurrences: &mut us
} }
} }
fn error_occurrences(term: &Term<Name>, occurrences: &mut usize) {
match term {
Term::Delay(body) => {
error_occurrences(body.as_ref(), occurrences);
}
Term::Lambda { body, .. } => {
error_occurrences(body.as_ref(), occurrences);
}
Term::Apply { function, argument } => {
error_occurrences(function.as_ref(), occurrences);
error_occurrences(argument.as_ref(), occurrences);
}
Term::Force(x) => {
error_occurrences(x.as_ref(), occurrences);
}
Term::Error => {
*occurrences += 1;
}
_ => {}
}
}
fn lambda_reduce(term: &mut Term<Name>) { fn lambda_reduce(term: &mut Term<Name>) {
match term { match term {
Term::Apply { function, argument } => { Term::Apply { function, argument } => {

View File

@ -0,0 +1,13 @@
# This file was generated by Aiken
# You typically do not need to edit this file
[[requirements]]
name = "aiken-lang/stdlib"
version = "1cedbe85b7c7e9c4036d63d45cad4ced27b0d50b"
source = "github"
[[packages]]
name = "aiken-lang/stdlib"
version = "1cedbe85b7c7e9c4036d63d45cad4ced27b0d50b"
requirements = []
source = "github"

View File

@ -0,0 +1,6 @@
name = "aiken-lang/acceptance_test_036"
version = "0.0.0"
dependencies = [
{ name = "aiken-lang/stdlib", version = "1cedbe85b7c7e9c4036d63d45cad4ced27b0d50b", source = "github" },
]

View File

@ -0,0 +1,8 @@
use aiken/dict
use aiken/list
use aiken/transaction/value.{Value}
test test_quantity_of_1() {
let x = value.from_asset(#"000000", #"000020e05363726970744f776e6572", -1)
value.quantity_of(x, #"000000", #"000020e05363726970744f776e6572") < 0
}