refactor the rest of the term builders to use more concise code
This commit is contained in:
@@ -4,10 +4,7 @@ use indexmap::{IndexMap, IndexSet};
|
||||
use itertools::Itertools;
|
||||
use uplc::{
|
||||
ast::{
|
||||
builder::{
|
||||
apply_wrap, constr_index_exposer, delayed_choose_list, delayed_if_else, if_else,
|
||||
CONSTR_FIELDS_EXPOSER,
|
||||
},
|
||||
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER},
|
||||
Constant as UplcConstant, Name, Term, Type as UplcType,
|
||||
},
|
||||
builtins::DefaultFunction,
|
||||
@@ -191,79 +188,39 @@ impl ClauseProperties {
|
||||
|
||||
pub fn convert_type_to_data(term: Term<Name>, field_type: &Arc<Type>) -> Term<Name> {
|
||||
if field_type.is_bytearray() {
|
||||
apply_wrap(DefaultFunction::BData.into(), term)
|
||||
Term::b_data().apply(term)
|
||||
} else if field_type.is_int() {
|
||||
apply_wrap(DefaultFunction::IData.into(), term)
|
||||
Term::i_data().apply(term)
|
||||
} else if field_type.is_void() {
|
||||
apply_wrap(
|
||||
apply_wrap(Term::Builtin(DefaultFunction::ChooseUnit).force(), term),
|
||||
Term::Constant(
|
||||
UplcConstant::Data(PlutusData::Constr(Constr {
|
||||
tag: convert_constr_to_tag(0).unwrap(),
|
||||
any_constructor: None,
|
||||
fields: vec![],
|
||||
}))
|
||||
.into(),
|
||||
),
|
||||
)
|
||||
term.choose_unit(Term::Constant(
|
||||
UplcConstant::Data(PlutusData::Constr(Constr {
|
||||
tag: convert_constr_to_tag(0).unwrap(),
|
||||
any_constructor: None,
|
||||
fields: vec![],
|
||||
}))
|
||||
.into(),
|
||||
))
|
||||
} else if field_type.is_map() {
|
||||
apply_wrap(DefaultFunction::MapData.into(), term)
|
||||
Term::map_data().apply(term)
|
||||
} else if field_type.is_string() {
|
||||
apply_wrap(
|
||||
DefaultFunction::BData.into(),
|
||||
apply_wrap(DefaultFunction::EncodeUtf8.into(), term),
|
||||
)
|
||||
Term::b_data().apply(Term::Builtin(DefaultFunction::EncodeUtf8).apply(term))
|
||||
} else if field_type.is_tuple() && matches!(field_type.get_uplc_type(), UplcType::Pair(_, _)) {
|
||||
apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__pair".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
DefaultFunction::ListData.into(),
|
||||
apply_wrap(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::MkCons).force(),
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::FstPair).force().force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: "__pair".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
),
|
||||
apply_wrap(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::MkCons).force(),
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::SndPair).force().force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: "__pair".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
),
|
||||
Term::Constant(UplcConstant::ProtoList(UplcType::Data, vec![]).into()),
|
||||
),
|
||||
Term::list_data()
|
||||
.apply(
|
||||
Term::mk_cons()
|
||||
.apply(Term::fst_pair().apply(Term::var("__pair".to_string())))
|
||||
.apply(
|
||||
Term::mk_cons()
|
||||
.apply(Term::snd_pair().apply(Term::var("__pair".to_string())))
|
||||
.apply(Term::empty_list()),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
},
|
||||
term,
|
||||
)
|
||||
)
|
||||
.lambda("__pair".to_string())
|
||||
.apply(term)
|
||||
} else if field_type.is_list() || field_type.is_tuple() {
|
||||
apply_wrap(DefaultFunction::ListData.into(), term)
|
||||
Term::list_data().apply(term)
|
||||
} else if field_type.is_bool() {
|
||||
if_else(
|
||||
term,
|
||||
term.if_else(
|
||||
Term::Constant(
|
||||
UplcConstant::Data(PlutusData::Constr(Constr {
|
||||
tag: convert_constr_to_tag(1).unwrap(),
|
||||
@@ -288,101 +245,32 @@ pub fn convert_type_to_data(term: Term<Name>, field_type: &Arc<Type>) -> Term<Na
|
||||
|
||||
pub fn convert_data_to_type(term: Term<Name>, field_type: &Arc<Type>) -> Term<Name> {
|
||||
if field_type.is_int() {
|
||||
apply_wrap(DefaultFunction::UnIData.into(), term)
|
||||
Term::un_i_data().apply(term)
|
||||
} else if field_type.is_bytearray() {
|
||||
apply_wrap(DefaultFunction::UnBData.into(), term)
|
||||
Term::un_b_data().apply(term)
|
||||
} else if field_type.is_void() {
|
||||
delayed_if_else(
|
||||
apply_wrap(
|
||||
apply_wrap(
|
||||
DefaultFunction::EqualsInteger.into(),
|
||||
Term::Constant(UplcConstant::Integer(0.into()).into()),
|
||||
),
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::FstPair).force().force(),
|
||||
apply_wrap(DefaultFunction::UnConstrData.into(), term),
|
||||
),
|
||||
),
|
||||
Term::Constant(UplcConstant::Unit.into()),
|
||||
Term::Error,
|
||||
)
|
||||
Term::equals_integer()
|
||||
.apply(Term::integer(0.into()))
|
||||
.apply(Term::fst_pair().apply(Term::unconstr_data().apply(term)))
|
||||
.delayed_if_else(Term::unit(), Term::Error)
|
||||
} else if field_type.is_map() {
|
||||
apply_wrap(DefaultFunction::UnMapData.into(), term)
|
||||
Term::unmap_data().apply(term)
|
||||
} else if field_type.is_string() {
|
||||
apply_wrap(
|
||||
DefaultFunction::DecodeUtf8.into(),
|
||||
apply_wrap(DefaultFunction::UnBData.into(), term),
|
||||
)
|
||||
Term::Builtin(DefaultFunction::DecodeUtf8).apply(Term::un_b_data().apply(term))
|
||||
} else if field_type.is_tuple() && matches!(field_type.get_uplc_type(), UplcType::Pair(_, _)) {
|
||||
apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__list_data".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__tail".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::MkPairData),
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::HeadList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: "__list_data".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
),
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::HeadList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: "__tail".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
},
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::TailList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: "__list_data".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
},
|
||||
apply_wrap(Term::Builtin(DefaultFunction::UnListData), term),
|
||||
)
|
||||
Term::mk_pair_data()
|
||||
.apply(Term::head_list().apply(Term::var("__list_data")))
|
||||
.apply(Term::head_list().apply(Term::var("__tail".to_string())))
|
||||
.lambda("__tail".to_string())
|
||||
.apply(Term::tail_list().apply(Term::var("__list_data")))
|
||||
.lambda("__list_data")
|
||||
.apply(Term::unlist_data().apply(term))
|
||||
} else if field_type.is_list() || field_type.is_tuple() {
|
||||
apply_wrap(DefaultFunction::UnListData.into(), term)
|
||||
Term::unlist_data().apply(term)
|
||||
} else if field_type.is_bool() {
|
||||
apply_wrap(
|
||||
apply_wrap(
|
||||
DefaultFunction::EqualsInteger.into(),
|
||||
Term::Constant(UplcConstant::Integer(1.into()).into()),
|
||||
),
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::FstPair).force().force(),
|
||||
apply_wrap(DefaultFunction::UnConstrData.into(), term),
|
||||
),
|
||||
)
|
||||
Term::equals_integer()
|
||||
.apply(Term::integer(1.into()))
|
||||
.apply(Term::fst_pair().apply(Term::unconstr_data().apply(term)))
|
||||
} else {
|
||||
term
|
||||
}
|
||||
@@ -564,246 +452,97 @@ pub fn list_access_to_uplc(
|
||||
if let Some((first, names)) = names.split_first() {
|
||||
let (current_tipo, tipos) = tipos.split_first().unwrap();
|
||||
|
||||
let head_list = if matches!(current_tipo.get_uplc_type(), UplcType::Pair(_, _))
|
||||
&& is_list_accessor
|
||||
{
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::HeadList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
convert_data_to_type(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::HeadList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
¤t_tipo.to_owned(),
|
||||
)
|
||||
};
|
||||
let head_list =
|
||||
if matches!(current_tipo.get_uplc_type(), UplcType::Pair(_, _)) && is_list_accessor {
|
||||
Term::head_list().apply(Term::var(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
)))
|
||||
} else {
|
||||
convert_data_to_type(
|
||||
Term::head_list().apply(Term::var(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))),
|
||||
¤t_tipo.to_owned(),
|
||||
)
|
||||
};
|
||||
|
||||
if names.len() == 1 && tail {
|
||||
if first == "_" && names[0] == "_" {
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "_".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: term.into(),
|
||||
}
|
||||
term.lambda("_".to_string())
|
||||
} else if first == "_" {
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: names[0].clone(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: term.into(),
|
||||
},
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::TailList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
term.lambda(names[0].clone())
|
||||
.apply(Term::tail_list().apply(Term::var(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))))
|
||||
.lambda(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))
|
||||
} else if names[0] == "_" {
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: first.clone(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: term.into(),
|
||||
},
|
||||
head_list,
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
term.lambda(first.clone()).apply(head_list).lambda(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))
|
||||
} else {
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: first.clone(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: names[0].clone(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: term.into(),
|
||||
},
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::TailList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
},
|
||||
head_list,
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
term.lambda(names[0].clone())
|
||||
.apply(Term::tail_list().apply(Term::var(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))))
|
||||
.lambda(first.clone())
|
||||
.apply(head_list)
|
||||
.lambda(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))
|
||||
}
|
||||
} else if names.is_empty() {
|
||||
if first == "_" {
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: if check_last_item {
|
||||
format!("tail_index_{}_{}", current_index, id_list[current_index])
|
||||
} else {
|
||||
"_".to_string()
|
||||
},
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: if check_last_item {
|
||||
delayed_choose_list(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::TailList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
if check_last_item {
|
||||
Term::tail_list()
|
||||
.apply(Term::var(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
)))
|
||||
.delayed_choose_list(
|
||||
term,
|
||||
apply_wrap(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::Trace).force(),
|
||||
Term::Constant(
|
||||
UplcConstant::String(
|
||||
"List/Tuple/Constr contains more items than expected"
|
||||
.to_string(),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
Term::Delay(Term::Error.into()),
|
||||
)
|
||||
.force(),
|
||||
Term::Error.trace(
|
||||
"List/Tuple/Constr contains more items than expected".to_string(),
|
||||
),
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
term.into()
|
||||
},
|
||||
} else {
|
||||
term
|
||||
}
|
||||
.lambda(if check_last_item {
|
||||
format!("tail_index_{}_{}", current_index, id_list[current_index])
|
||||
} else {
|
||||
"_".to_string()
|
||||
})
|
||||
} else {
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||
unique: 0.into(),
|
||||
if check_last_item {
|
||||
Term::tail_list()
|
||||
.apply(Term::var(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
)))
|
||||
.delayed_choose_list(
|
||||
term,
|
||||
Term::Error.trace(
|
||||
"List/Tuple/Constr contains more items than expected".to_string(),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
term
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: first.clone(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: if check_last_item {
|
||||
delayed_choose_list(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::TailList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
term,
|
||||
apply_wrap(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::Trace).force(),
|
||||
Term::Constant(
|
||||
UplcConstant::String(
|
||||
"List/Tuple/Constr contains more items than it expected"
|
||||
.to_string(),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
Term::Delay(Term::Error.into()),
|
||||
)
|
||||
.force(),
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
term.into()
|
||||
},
|
||||
},
|
||||
head_list,
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.lambda(first.clone())
|
||||
.apply(head_list)
|
||||
.lambda(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))
|
||||
}
|
||||
} else if first == "_" {
|
||||
let mut list_access_inner = list_access_to_uplc(
|
||||
@@ -825,33 +564,15 @@ pub fn list_access_to_uplc(
|
||||
if ¶meter_name.text == "_" {
|
||||
body.as_ref().clone()
|
||||
} else {
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
list_access_inner,
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::TailList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
list_access_inner
|
||||
.apply(Term::tail_list().apply(Term::var(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))))
|
||||
.lambda(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))
|
||||
}
|
||||
}
|
||||
_ => list_access_inner,
|
||||
@@ -859,14 +580,7 @@ pub fn list_access_to_uplc(
|
||||
|
||||
match &list_access_inner {
|
||||
Term::Lambda { .. } => list_access_inner,
|
||||
_ => Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "_".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: list_access_inner.into(),
|
||||
},
|
||||
_ => list_access_inner.lambda("_".to_string()),
|
||||
}
|
||||
} else {
|
||||
let mut list_access_inner = list_access_to_uplc(
|
||||
@@ -886,88 +600,35 @@ pub fn list_access_to_uplc(
|
||||
body,
|
||||
} => {
|
||||
if ¶meter_name.text == "_" {
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: first.clone(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: body.as_ref().clone().into(),
|
||||
},
|
||||
head_list,
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
body.as_ref()
|
||||
.clone()
|
||||
.lambda(first.clone())
|
||||
.apply(head_list)
|
||||
.lambda(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))
|
||||
} else {
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: first.clone(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
list_access_inner,
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::TailList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
},
|
||||
head_list,
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
list_access_inner
|
||||
.apply(Term::tail_list().apply(Term::var(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))))
|
||||
.lambda(first.clone())
|
||||
.apply(head_list)
|
||||
.lambda(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
))
|
||||
}
|
||||
}
|
||||
_ => Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: first.clone(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: list_access_inner.into(),
|
||||
},
|
||||
head_list,
|
||||
)
|
||||
.into(),
|
||||
},
|
||||
_ => list_access_inner
|
||||
.lambda(first.clone())
|
||||
.apply(head_list)
|
||||
.lambda(format!(
|
||||
"tail_index_{}_{}",
|
||||
current_index, id_list[current_index]
|
||||
)),
|
||||
};
|
||||
list_access_inner
|
||||
}
|
||||
@@ -1316,36 +977,15 @@ pub fn wrap_validator_args(term: Term<Name>, arguments: &[TypedArg]) -> Term<Nam
|
||||
let mut term = term;
|
||||
for arg in arguments.iter().rev() {
|
||||
if !matches!(arg.tipo.get_uplc_type(), UplcType::Data) {
|
||||
term = apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: arg.arg_name.get_variable_name().unwrap_or("_").to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: term.into(),
|
||||
},
|
||||
convert_data_to_type(
|
||||
Term::Var(
|
||||
Name {
|
||||
text: arg.arg_name.get_variable_name().unwrap_or("_").to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
term = term
|
||||
.lambda(arg.arg_name.get_variable_name().unwrap_or("_").to_string())
|
||||
.apply(convert_data_to_type(
|
||||
Term::var(arg.arg_name.get_variable_name().unwrap_or("_").to_string()),
|
||||
&arg.tipo,
|
||||
),
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
term = Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: arg.arg_name.get_variable_name().unwrap_or("_").to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: term.into(),
|
||||
}
|
||||
term = term.lambda(arg.arg_name.get_variable_name().unwrap_or("_").to_string())
|
||||
}
|
||||
term
|
||||
}
|
||||
@@ -1353,7 +993,7 @@ pub fn wrap_validator_args(term: Term<Name>, arguments: &[TypedArg]) -> Term<Nam
|
||||
pub fn wrap_as_multi_validator(spend: Term<Name>, mint: Term<Name>) -> Term<Name> {
|
||||
Term::equals_integer()
|
||||
.apply(Term::integer(0.into()))
|
||||
.apply(constr_index_exposer(Term::var("__second_arg")))
|
||||
.apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("__second_arg")))
|
||||
.delayed_if_else(
|
||||
mint.apply(Term::var("__first_arg"))
|
||||
.apply(Term::var("__second_arg")),
|
||||
|
||||
@@ -5,8 +5,8 @@ use itertools::Itertools;
|
||||
use uplc::{
|
||||
ast::{
|
||||
builder::{
|
||||
self, apply_wrap, assert_on_list, constr_index_exposer, final_wrapper,
|
||||
repeat_tail_list, ASSERT_ON_LIST, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD,
|
||||
self, assert_on_list, final_wrapper, repeat_tail_list, ASSERT_ON_LIST,
|
||||
CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, CONSTR_INDEX_EXPOSER,
|
||||
},
|
||||
Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType,
|
||||
},
|
||||
@@ -97,12 +97,6 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
let mut term = self.uplc_code_gen(&mut ir_stack);
|
||||
|
||||
if self.needs_field_access {
|
||||
term = builder::constr_get_field(term);
|
||||
|
||||
term = builder::constr_fields_exposer(term);
|
||||
}
|
||||
|
||||
// Wrap the validator body if ifThenElse term unit error
|
||||
term = final_wrapper(term);
|
||||
|
||||
@@ -134,9 +128,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
};
|
||||
|
||||
term = wrap_as_multi_validator(spend, mint);
|
||||
term = builder::constr_get_field(term);
|
||||
|
||||
term = builder::constr_fields_exposer(term);
|
||||
self.needs_field_access = true;
|
||||
}
|
||||
|
||||
term = wrap_validator_args(term, params);
|
||||
@@ -154,24 +146,26 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
self.convert_opaque_type_to_inner_ir(&mut ir_stack);
|
||||
|
||||
let mut term = self.uplc_code_gen(&mut ir_stack);
|
||||
|
||||
if self.needs_field_access {
|
||||
term = builder::constr_get_field(term);
|
||||
|
||||
term = builder::constr_fields_exposer(term);
|
||||
}
|
||||
let term = self.uplc_code_gen(&mut ir_stack);
|
||||
|
||||
self.finalize(term, false)
|
||||
}
|
||||
|
||||
fn finalize(&mut self, term: Term<Name>, wrap_as_validator: bool) -> Program<Name> {
|
||||
let term = if wrap_as_validator || self.used_data_assert_on_list {
|
||||
let mut term = if wrap_as_validator || self.used_data_assert_on_list {
|
||||
assert_on_list(term)
|
||||
} else {
|
||||
term
|
||||
};
|
||||
|
||||
if self.needs_field_access {
|
||||
term = builder::constr_get_field(term);
|
||||
|
||||
term = builder::constr_fields_exposer(term);
|
||||
|
||||
term = builder::constr_index_exposer(term);
|
||||
}
|
||||
|
||||
let mut program = Program {
|
||||
version: (1, 0, 0),
|
||||
term,
|
||||
@@ -708,8 +702,6 @@ impl<'a> CodeGenerator<'a> {
|
||||
tipo,
|
||||
..
|
||||
} => {
|
||||
self.needs_field_access = true;
|
||||
|
||||
ir_stack.push(Air::RecordAccess {
|
||||
scope: scope.clone(),
|
||||
record_index: *index,
|
||||
@@ -4508,41 +4500,31 @@ impl<'a> CodeGenerator<'a> {
|
||||
.apply(right)
|
||||
.if_else(Term::bool(false), Term::bool(true))
|
||||
}
|
||||
BinOp::LtInt => apply_wrap(
|
||||
apply_wrap(DefaultFunction::LessThanInteger.into(), left),
|
||||
right,
|
||||
),
|
||||
|
||||
BinOp::LtEqInt => apply_wrap(
|
||||
apply_wrap(DefaultFunction::LessThanEqualsInteger.into(), left),
|
||||
right,
|
||||
),
|
||||
BinOp::GtEqInt => apply_wrap(
|
||||
apply_wrap(DefaultFunction::LessThanEqualsInteger.into(), right),
|
||||
left,
|
||||
),
|
||||
BinOp::GtInt => apply_wrap(
|
||||
apply_wrap(DefaultFunction::LessThanInteger.into(), right),
|
||||
left,
|
||||
),
|
||||
BinOp::AddInt => {
|
||||
apply_wrap(apply_wrap(DefaultFunction::AddInteger.into(), left), right)
|
||||
}
|
||||
BinOp::SubInt => apply_wrap(
|
||||
apply_wrap(DefaultFunction::SubtractInteger.into(), left),
|
||||
right,
|
||||
),
|
||||
BinOp::MultInt => apply_wrap(
|
||||
apply_wrap(DefaultFunction::MultiplyInteger.into(), left),
|
||||
right,
|
||||
),
|
||||
BinOp::DivInt => apply_wrap(
|
||||
apply_wrap(DefaultFunction::DivideInteger.into(), left),
|
||||
right,
|
||||
),
|
||||
BinOp::ModInt => {
|
||||
apply_wrap(apply_wrap(DefaultFunction::ModInteger.into(), left), right)
|
||||
}
|
||||
BinOp::LtInt => Term::Builtin(DefaultFunction::LessThanInteger)
|
||||
.apply(left)
|
||||
.apply(right),
|
||||
BinOp::LtEqInt => Term::Builtin(DefaultFunction::LessThanEqualsInteger)
|
||||
.apply(left)
|
||||
.apply(right),
|
||||
BinOp::GtEqInt => Term::Builtin(DefaultFunction::LessThanEqualsInteger)
|
||||
.apply(right)
|
||||
.apply(left),
|
||||
BinOp::GtInt => Term::Builtin(DefaultFunction::LessThanInteger)
|
||||
.apply(right)
|
||||
.apply(left),
|
||||
BinOp::AddInt => Term::add_integer().apply(left).apply(right),
|
||||
BinOp::SubInt => Term::Builtin(DefaultFunction::SubtractInteger)
|
||||
.apply(left)
|
||||
.apply(right),
|
||||
BinOp::MultInt => Term::Builtin(DefaultFunction::MultiplyInteger)
|
||||
.apply(left)
|
||||
.apply(right),
|
||||
BinOp::DivInt => Term::Builtin(DefaultFunction::DivideInteger)
|
||||
.apply(left)
|
||||
.apply(right),
|
||||
BinOp::ModInt => Term::Builtin(DefaultFunction::ModInteger)
|
||||
.apply(left)
|
||||
.apply(right),
|
||||
};
|
||||
arg_stack.push(term);
|
||||
}
|
||||
@@ -4607,6 +4589,7 @@ 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();
|
||||
@@ -4616,7 +4599,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
term = Term::equals_integer()
|
||||
.apply(Term::integer(constr_index.into()))
|
||||
.apply(constr_index_exposer(constr))
|
||||
.apply(Term::var(CONSTR_INDEX_EXPOSER.to_string()).apply(constr))
|
||||
.delayed_if_else(term, error_term);
|
||||
|
||||
arg_stack.push(term);
|
||||
@@ -4638,6 +4621,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
Air::When {
|
||||
subject_name, tipo, ..
|
||||
} => {
|
||||
self.needs_field_access = true;
|
||||
let subject = arg_stack.pop().unwrap();
|
||||
|
||||
let subject = if tipo.is_int()
|
||||
@@ -4649,7 +4633,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
{
|
||||
subject
|
||||
} else {
|
||||
constr_index_exposer(subject)
|
||||
Term::var(CONSTR_INDEX_EXPOSER).apply(subject)
|
||||
};
|
||||
|
||||
let mut term = arg_stack.pop().unwrap();
|
||||
@@ -4813,7 +4797,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
} else {
|
||||
Term::equals_integer()
|
||||
.apply(checker)
|
||||
.apply(constr_index_exposer(Term::var(subject_name)))
|
||||
.apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var(subject_name)))
|
||||
};
|
||||
|
||||
let term = condition
|
||||
@@ -5031,6 +5015,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
indices,
|
||||
..
|
||||
} => {
|
||||
self.needs_field_access = true;
|
||||
let tail_name_prefix = "__tail_index".to_string();
|
||||
|
||||
let record = arg_stack.pop().unwrap();
|
||||
@@ -5105,7 +5090,6 @@ impl<'a> CodeGenerator<'a> {
|
||||
term = term.lambda(tail_name).apply(tail_list);
|
||||
}
|
||||
|
||||
self.needs_field_access = true;
|
||||
term = term
|
||||
.lambda(prev_tail_name)
|
||||
.apply(Term::var(CONSTR_FIELDS_EXPOSER.to_string()).apply(record));
|
||||
|
||||
@@ -50,6 +50,10 @@ impl Term<Name> {
|
||||
Term::Constant(Constant::Bool(b).into())
|
||||
}
|
||||
|
||||
pub fn unit() -> Self {
|
||||
Term::Constant(Constant::Unit.into())
|
||||
}
|
||||
|
||||
pub fn empty_list() -> Self {
|
||||
Term::Constant(Constant::ProtoList(Type::Data, vec![]).into())
|
||||
}
|
||||
@@ -80,6 +84,26 @@ impl Term<Name> {
|
||||
Term::Builtin(DefaultFunction::IData)
|
||||
}
|
||||
|
||||
pub fn unconstr_data() -> Self {
|
||||
Term::Builtin(DefaultFunction::UnConstrData)
|
||||
}
|
||||
|
||||
pub fn un_i_data() -> Self {
|
||||
Term::Builtin(DefaultFunction::UnIData)
|
||||
}
|
||||
|
||||
pub fn un_b_data() -> Self {
|
||||
Term::Builtin(DefaultFunction::UnBData)
|
||||
}
|
||||
|
||||
pub fn unmap_data() -> Self {
|
||||
Term::Builtin(DefaultFunction::UnMapData)
|
||||
}
|
||||
|
||||
pub fn unlist_data() -> Self {
|
||||
Term::Builtin(DefaultFunction::UnListData)
|
||||
}
|
||||
|
||||
pub fn equals_integer() -> Self {
|
||||
Term::Builtin(DefaultFunction::EqualsInteger)
|
||||
}
|
||||
@@ -145,6 +169,21 @@ impl Term<Name> {
|
||||
.apply(else_term)
|
||||
}
|
||||
|
||||
pub fn choose_unit(self, then_term: Self) -> Self {
|
||||
Term::Builtin(DefaultFunction::ChooseUnit)
|
||||
.force()
|
||||
.apply(self)
|
||||
.apply(then_term)
|
||||
}
|
||||
|
||||
pub fn delayed_choose_unit(self, then_term: Self) -> Self {
|
||||
Term::Builtin(DefaultFunction::ChooseUnit)
|
||||
.force()
|
||||
.apply(self)
|
||||
.apply(then_term.delay())
|
||||
.force()
|
||||
}
|
||||
|
||||
pub fn delayed_if_else(self, then_term: Self, else_term: Self) -> Self {
|
||||
Term::Builtin(DefaultFunction::IfThenElse)
|
||||
.force()
|
||||
@@ -173,540 +212,93 @@ impl Term<Name> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_wrap(function: Term<Name>, arg: Term<Name>) -> Term<Name> {
|
||||
Term::Apply {
|
||||
function: function.into(),
|
||||
argument: arg.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn final_wrapper(term: Term<Name>) -> Term<Name> {
|
||||
Term::Force(
|
||||
Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Force(Term::Builtin(DefaultFunction::IfThenElse).into()).into(),
|
||||
argument: term.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(Term::Constant(Constant::Unit.into()).into()).into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(Term::Error.into()).into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
term.delayed_if_else(Term::unit(), Term::Error)
|
||||
}
|
||||
|
||||
pub fn assert_on_list(term: Term<Name>) -> Term<Name> {
|
||||
apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: ASSERT_ON_LIST.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: ASSERT_ON_LIST.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: term.into(),
|
||||
},
|
||||
apply_wrap(
|
||||
Term::Var(
|
||||
Name {
|
||||
text: ASSERT_ON_LIST.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: ASSERT_ON_LIST.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
},
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: ASSERT_ON_LIST.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "list_to_check".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "check_with".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: delayed_choose_list(
|
||||
Term::Var(
|
||||
Name {
|
||||
text: "list_to_check".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
term.lambda(ASSERT_ON_LIST.to_string())
|
||||
.apply(Term::var(ASSERT_ON_LIST.to_string()).apply(Term::var(ASSERT_ON_LIST.to_string())))
|
||||
.lambda(ASSERT_ON_LIST.to_string())
|
||||
.apply(
|
||||
Term::var("__list_to_check".to_string())
|
||||
.delayed_choose_list(
|
||||
Term::unit(),
|
||||
Term::var("__check_with".to_string())
|
||||
.apply(Term::head_list().apply(Term::var("__list_to_check".to_string())))
|
||||
.choose_unit(
|
||||
Term::var(ASSERT_ON_LIST.to_string())
|
||||
.apply(Term::var(ASSERT_ON_LIST.to_string()))
|
||||
.apply(
|
||||
Term::tail_list()
|
||||
.apply(Term::var("__list_to_check".to_string())),
|
||||
)
|
||||
.apply(Term::var("__check_with".to_string())),
|
||||
),
|
||||
Term::Constant(Constant::Unit.into()),
|
||||
apply_wrap(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::ChooseUnit).force(),
|
||||
apply_wrap(
|
||||
Term::Var(
|
||||
Name {
|
||||
text: "check_with".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::HeadList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: "list_to_check".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
apply_wrap(
|
||||
apply_wrap(
|
||||
apply_wrap(
|
||||
Term::Var(
|
||||
Name {
|
||||
text: ASSERT_ON_LIST.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: ASSERT_ON_LIST.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::TailList).force(),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: "list_to_check".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
),
|
||||
Term::Var(
|
||||
Name {
|
||||
text: "check_with".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
},
|
||||
)
|
||||
)
|
||||
.lambda("__check_with".to_string())
|
||||
.lambda("__list_to_check".to_string())
|
||||
.lambda(ASSERT_ON_LIST),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn constr_fields_exposer(term: Term<Name>) -> Term<Name> {
|
||||
Term::Apply {
|
||||
function: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: CONSTR_FIELDS_EXPOSER.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: term.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__constr_var".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Force(Term::Builtin(DefaultFunction::SndPair).into()).into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Apply {
|
||||
function: Term::Builtin(DefaultFunction::UnConstrData).into(),
|
||||
argument: Term::Var(
|
||||
Name {
|
||||
text: "__constr_var".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
term.lambda(CONSTR_FIELDS_EXPOSER.to_string()).apply(
|
||||
Term::snd_pair()
|
||||
.apply(Term::unconstr_data().apply(Term::var("__constr_var".to_string())))
|
||||
.lambda("__constr_var"),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn constr_index_exposer(term: Term<Name>) -> Term<Name> {
|
||||
Term::Apply {
|
||||
function: Term::Force(Term::Force(Term::Builtin(DefaultFunction::FstPair).into()).into())
|
||||
.into(),
|
||||
argument: Term::Apply {
|
||||
function: Term::Builtin(DefaultFunction::UnConstrData).into(),
|
||||
argument: term.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
term.lambda(CONSTR_INDEX_EXPOSER.to_string()).apply(
|
||||
Term::fst_pair()
|
||||
.apply(Term::unconstr_data().apply(Term::var("__constr_var".to_string())))
|
||||
.lambda("__constr_var".to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn constr_get_field(term: Term<Name>) -> Term<Name> {
|
||||
Term::Apply {
|
||||
function: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: CONSTR_GET_FIELD.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: term.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__constr_list".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__arg_number".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: Term::Apply {
|
||||
function: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__recurse".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Var(
|
||||
Name {
|
||||
text: "__recurse".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(
|
||||
Name {
|
||||
text: "__recurse".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
|
||||
// Start recursive with index 0 of list
|
||||
argument: Term::Constant(Constant::Integer(0.into()).into()).into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Var(
|
||||
Name {
|
||||
text: "__constr_list".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
|
||||
argument: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__self_recursor".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__current_arg_number".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__list_of_constr_args".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Builtin(DefaultFunction::IfThenElse)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Builtin(
|
||||
DefaultFunction::EqualsInteger,
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(
|
||||
Name {
|
||||
text: "__arg_number".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Var(
|
||||
Name {
|
||||
text: "__current_arg_number"
|
||||
.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Force(
|
||||
Term::Builtin(DefaultFunction::HeadList).into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: "__current_list_of_constr_args".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Var(
|
||||
Name {
|
||||
text: "__self_recursor".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(
|
||||
Name {
|
||||
text: "__self_recursor".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
|
||||
argument: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Builtin(
|
||||
DefaultFunction::AddInteger,
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(
|
||||
Name {
|
||||
text: "__current_arg_number"
|
||||
.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Constant(
|
||||
Constant::Integer(1.into()).into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
|
||||
argument: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Builtin(DefaultFunction::TailList)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
|
||||
argument: Term::Var(
|
||||
Name {
|
||||
text: "__current_list_of_constr_args"
|
||||
.to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Var(
|
||||
Name {
|
||||
text: "__list_of_constr_args".to_string(),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delayed_if_else(
|
||||
condition: Term<Name>,
|
||||
then_term: Term<Name>,
|
||||
else_term: Term<Name>,
|
||||
) -> Term<Name> {
|
||||
Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Builtin(DefaultFunction::IfThenElse).force().into(),
|
||||
argument: condition.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(then_term.into()).into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(else_term.into()).into(),
|
||||
}
|
||||
.force()
|
||||
}
|
||||
|
||||
pub fn if_else(condition: Term<Name>, then_term: Term<Name>, else_term: Term<Name>) -> Term<Name> {
|
||||
Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Builtin(DefaultFunction::IfThenElse).force().into(),
|
||||
argument: condition.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: then_term.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: else_term.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delayed_choose_list(
|
||||
list: Term<Name>,
|
||||
empty_list_term: Term<Name>,
|
||||
else_term: Term<Name>,
|
||||
) -> Term<Name> {
|
||||
Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Builtin(DefaultFunction::ChooseList)
|
||||
.force()
|
||||
.force()
|
||||
.into(),
|
||||
argument: list.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(empty_list_term.into()).into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(else_term.into()).into(),
|
||||
}
|
||||
.force()
|
||||
}
|
||||
|
||||
pub fn choose_list(
|
||||
list: Term<Name>,
|
||||
empty_list_term: Term<Name>,
|
||||
else_term: Term<Name>,
|
||||
) -> Term<Name> {
|
||||
Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Builtin(DefaultFunction::ChooseList)
|
||||
.force()
|
||||
.force()
|
||||
.into(),
|
||||
argument: list.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: empty_list_term.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: else_term.into(),
|
||||
}
|
||||
term.lambda(CONSTR_GET_FIELD.to_string())
|
||||
.apply(
|
||||
Term::var(CONSTR_GET_FIELD.to_string())
|
||||
.apply(Term::var(CONSTR_GET_FIELD.to_string()))
|
||||
.apply(Term::integer(0.into())),
|
||||
)
|
||||
.lambda(CONSTR_GET_FIELD)
|
||||
.apply(
|
||||
Term::equals_integer()
|
||||
.apply(Term::var("__wanted_arg".to_string()))
|
||||
.apply(Term::var("__current_arg_number".to_string()))
|
||||
.if_else(
|
||||
Term::head_list(),
|
||||
Term::var(CONSTR_GET_FIELD)
|
||||
.apply(Term::var(CONSTR_GET_FIELD))
|
||||
.apply(
|
||||
Term::add_integer()
|
||||
.apply(Term::var("__current_arg_number".to_string()))
|
||||
.apply(Term::integer(1.into())),
|
||||
)
|
||||
.apply(
|
||||
Term::tail_list()
|
||||
.apply(Term::var("__current_list_of_constr_args".to_string())),
|
||||
)
|
||||
.apply(Term::var("__wanted_arg"))
|
||||
.lambda("__current_list_of_constr_args".to_string()),
|
||||
)
|
||||
.apply(Term::var("__list_of_constr_args".to_string()))
|
||||
.lambda("__wanted_arg".to_string())
|
||||
.lambda("__list_of_constr_args")
|
||||
.lambda("__current_arg_number".to_string())
|
||||
.lambda(CONSTR_GET_FIELD.to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn repeat_tail_list(term: Term<Name>, repeat: usize) -> Term<Name> {
|
||||
let mut term = term;
|
||||
|
||||
for _ in 0..repeat {
|
||||
term = Term::Apply {
|
||||
function: Term::Builtin(DefaultFunction::TailList).force().into(),
|
||||
argument: term.into(),
|
||||
};
|
||||
term = Term::tail_list().apply(term);
|
||||
}
|
||||
term
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::{
|
||||
ast::{builder::apply_wrap, Name, Program, Term},
|
||||
ast::{Name, Program, Term},
|
||||
builtins::DefaultFunction,
|
||||
};
|
||||
// use crate::builtins::{DefaultFunction};
|
||||
@@ -33,21 +33,13 @@ impl Program<Name> {
|
||||
for default_func_index in builtin_map.keys().sorted().cloned() {
|
||||
let default_func: DefaultFunction = default_func_index.try_into().unwrap();
|
||||
|
||||
term = apply_wrap(
|
||||
Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!("__{}_wrapped", default_func.aiken_name()),
|
||||
unique: 0.into(),
|
||||
}
|
||||
.into(),
|
||||
body: term.into(),
|
||||
},
|
||||
if default_func.force_count() == 1 {
|
||||
term = term
|
||||
.lambda(format!("__{}_wrapped", default_func.aiken_name()))
|
||||
.apply(if default_func.force_count() == 1 {
|
||||
Term::Builtin(default_func).force()
|
||||
} else {
|
||||
Term::Builtin(default_func).force().force()
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Program {
|
||||
|
||||
Reference in New Issue
Block a user