fix: Various fixes for FieldsExpose, ListAccessor, TupleAccessor
This commit is contained in:
parent
cf7a20b986
commit
986a6009f7
|
@ -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:#?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 } => {
|
||||||
|
|
|
@ -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"
|
|
@ -0,0 +1,6 @@
|
||||||
|
name = "aiken-lang/acceptance_test_036"
|
||||||
|
version = "0.0.0"
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
{ name = "aiken-lang/stdlib", version = "1cedbe85b7c7e9c4036d63d45cad4ced27b0d50b", source = "github" },
|
||||||
|
]
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue