cleanup if then else a bit

This commit is contained in:
Kasey White 2022-12-15 02:32:48 -05:00 committed by Lucas
parent eddd202253
commit e6c59dca2c
2 changed files with 97 additions and 201 deletions

View File

@ -4,7 +4,10 @@ use indexmap::IndexMap;
use itertools::Itertools; use itertools::Itertools;
use uplc::{ use uplc::{
ast::{ ast::{
builder::{self, constr_index_exposer, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD}, builder::{
self, constr_index_exposer, delayed_if_else, if_else, CONSTR_FIELDS_EXPOSER,
CONSTR_GET_FIELD,
},
Constant as UplcConstant, Name, Program, Term, Type as UplcType, Constant as UplcConstant, Name, Program, Term, Type as UplcType,
}, },
builtins::DefaultFunction, builtins::DefaultFunction,
@ -2453,80 +2456,24 @@ impl<'a> CodeGenerator<'a> {
}; };
let term = match name { let term = match name {
BinOp::And => Term::Apply { BinOp::And => {
function: Term::Apply { delayed_if_else(left, right, Term::Constant(UplcConstant::Bool(false)))
function: Term::Apply {
function: Term::Builtin(DefaultFunction::IfThenElse)
.force_wrap()
.into(),
argument: left.into(),
} }
.into(), BinOp::Or => {
argument: Term::Delay(right.into()).into(), delayed_if_else(left, Term::Constant(UplcConstant::Bool(true)), right)
} }
.into(),
argument: Term::Delay(Term::Constant(UplcConstant::Bool(false)).into())
.into(),
}
.force_wrap(),
BinOp::Or => Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::IfThenElse)
.force_wrap()
.into(),
argument: left.into(),
}
.into(),
argument: Term::Delay(Term::Constant(UplcConstant::Bool(true)).into())
.into(),
}
.into(),
argument: Term::Delay(right.into()).into(),
}
.force_wrap(),
BinOp::Eq => { BinOp::Eq => {
if tipo.is_bool() { if tipo.is_bool() {
let term = Term::Force( let term = delayed_if_else(
Term::Apply { left,
function: Term::Apply { right.clone(),
function: Term::Apply { if_else(
function: Term::Force( right,
Term::Builtin(DefaultFunction::IfThenElse).into(), Term::Constant(UplcConstant::Bool(false)),
) Term::Constant(UplcConstant::Bool(true)),
.into(), ),
argument: left.into(),
}
.into(),
argument: Term::Delay(right.clone().into()).into(),
}
.into(),
argument: Term::Delay(
Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Force(
Term::Builtin(DefaultFunction::IfThenElse)
.into(),
)
.into(),
argument: right.into(),
}
.into(),
argument: Term::Constant(UplcConstant::Bool(false))
.into(),
}
.into(),
argument: Term::Constant(UplcConstant::Bool(true))
.into(),
}
.into(),
)
.into(),
}
.into(),
); );
arg_stack.push(term); arg_stack.push(term);
return; return;
} else if tipo.is_map() { } else if tipo.is_map() {
@ -2636,50 +2583,15 @@ impl<'a> CodeGenerator<'a> {
} }
BinOp::NotEq => { BinOp::NotEq => {
if tipo.is_bool() { if tipo.is_bool() {
let term = Term::Force( let term = delayed_if_else(
Term::Apply { left,
function: Term::Apply { if_else(
function: Term::Apply { right.clone(),
function: Term::Force( Term::Constant(UplcConstant::Bool(false)),
Term::Builtin(DefaultFunction::IfThenElse).into(), Term::Constant(UplcConstant::Bool(true)),
) ),
.into(), right,
argument: left.into(),
}
.into(),
argument: Term::Delay(
Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Force(
Term::Builtin(
DefaultFunction::IfThenElse,
)
.into(),
)
.into(),
argument: right.clone().into(),
}
.into(),
argument: Term::Constant(UplcConstant::Bool(
false,
))
.into(),
}
.into(),
argument: Term::Constant(UplcConstant::Bool(true))
.into(),
}
.into(),
)
.into(),
}
.into(),
argument: Term::Delay(right.into()).into(),
}
.into(),
); );
arg_stack.push(term); arg_stack.push(term);
return; return;
} else if tipo.is_map() { } else if tipo.is_map() {
@ -3156,28 +3068,18 @@ impl<'a> CodeGenerator<'a> {
text: "__other_clauses_delayed".to_string(), text: "__other_clauses_delayed".to_string(),
unique: 0.into(), unique: 0.into(),
}, },
body: Term::Apply { body: if_else(
function: Term::Apply { Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::IfThenElse)
.force_wrap()
.into(),
argument: Term::Apply {
function: checker.into(), function: checker.into(),
argument: clause.into(), argument: clause.into(),
} },
.into(), Term::Delay(body.into()),
} Term::Var(Name {
.into(),
argument: Term::Delay(body.into()).into(),
}
.into(),
argument: Term::Var(Name {
text: "__other_clauses_delayed".to_string(), text: "__other_clauses_delayed".to_string(),
unique: 0.into(), unique: 0.into(),
}) }),
.into(), )
} .force_wrap()
.into(), .into(),
} }
.into(), .into(),
@ -3185,23 +3087,14 @@ impl<'a> CodeGenerator<'a> {
} }
.force_wrap() .force_wrap()
} else { } else {
term = Term::Apply { term = delayed_if_else(
function: Term::Apply { Term::Apply {
function: Term::Apply {
function: Term::Force(DefaultFunction::IfThenElse.into()).into(),
argument: Term::Apply {
function: checker.into(), function: checker.into(),
argument: clause.into(), argument: clause.into(),
} },
.into(), body,
} term,
.into(), );
argument: Term::Delay(body.into()).into(),
}
.into(),
argument: Term::Delay(term.into()).into(),
}
.force_wrap();
} }
arg_stack.push(term); arg_stack.push(term);
@ -3316,28 +3209,17 @@ impl<'a> CodeGenerator<'a> {
} }
}; };
let term = Term::Apply { let term = if_else(
function: Term::Apply { Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::IfThenElse)
.force_wrap()
.into(),
argument: Term::Apply {
function: checker.into(), function: checker.into(),
argument: condition.into(), argument: condition.into(),
} },
.into(), Term::Delay(then.into()),
} Term::Var(Name {
.into(),
argument: Term::Delay(then.into()).into(),
}
.into(),
argument: Term::Var(Name {
text: "__other_clauses_delayed".to_string(), text: "__other_clauses_delayed".to_string(),
unique: 0.into(), unique: 0.into(),
}) }),
.into(), )
}
.force_wrap(); .force_wrap();
arg_stack.push(term); arg_stack.push(term);
@ -3350,23 +3232,7 @@ impl<'a> CodeGenerator<'a> {
let then = arg_stack.pop().unwrap(); let then = arg_stack.pop().unwrap();
let mut term = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap();
term = Term::Force( term = delayed_if_else(condition, then, term);
Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::IfThenElse)
.force_wrap()
.into(),
argument: condition.into(),
}
.into(),
argument: Term::Delay(then.into()).into(),
}
.into(),
argument: Term::Delay(term.into()).into(),
}
.into(),
);
arg_stack.push(term); arg_stack.push(term);
} }
@ -3647,20 +3513,11 @@ impl<'a> CodeGenerator<'a> {
Air::Negate { .. } => { Air::Negate { .. } => {
let value = arg_stack.pop().unwrap(); let value = arg_stack.pop().unwrap();
let term = Term::Apply { let term = if_else(
function: Term::Apply { value,
function: Term::Apply { Term::Constant(UplcConstant::Bool(false)),
function: Term::Builtin(DefaultFunction::IfThenElse) Term::Constant(UplcConstant::Bool(true)),
.force_wrap() );
.into(),
argument: value.into(),
}
.into(),
argument: Term::Constant(UplcConstant::Bool(false)).into(),
}
.into(),
argument: Term::Constant(UplcConstant::Bool(true)).into(),
};
arg_stack.push(term); arg_stack.push(term);
} }
Air::TupleAccessor { tipo, names, .. } => { Air::TupleAccessor { tipo, names, .. } => {

View File

@ -266,3 +266,42 @@ pub fn constr_get_field(term: Term<Name>) -> Term<Name> {
.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_wrap()
.into(),
argument: condition.into(),
}
.into(),
argument: Term::Delay(then_term.into()).into(),
}
.into(),
argument: Term::Delay(else_term.into()).into(),
}
.force_wrap()
}
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_wrap()
.into(),
argument: condition.into(),
}
.into(),
argument: then_term.into(),
}
.into(),
argument: else_term.into(),
}
}