refactor the rest of the term builders to use more concise code
This commit is contained in:
@@ -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