feat: finish up binops and fix constr creation

This commit is contained in:
Kasey White 2022-12-05 02:42:03 -05:00 committed by Lucas
parent 0fda535c50
commit 22fbef2fbe
2 changed files with 192 additions and 20 deletions

View File

@ -219,6 +219,10 @@ pub enum IR {
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
Record {
scope: Vec<u64>,
},
RecordUpdate { RecordUpdate {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
@ -264,6 +268,7 @@ impl IR {
| IR::RecordAccess { scope, .. } | IR::RecordAccess { scope, .. }
| IR::FieldsExpose { scope, .. } | IR::FieldsExpose { scope, .. }
| IR::Todo { scope, .. } | IR::Todo { scope, .. }
| IR::Record { scope, .. }
| IR::RecordUpdate { scope, .. } | IR::RecordUpdate { scope, .. }
| IR::Negate { scope, .. } => scope.to_vec(), | IR::Negate { scope, .. } => scope.to_vec(),
} }

View File

@ -1383,7 +1383,9 @@ impl<'a> CodeGenerator<'a> {
})); }));
} }
ValueConstructorVariant::Record { ValueConstructorVariant::Record {
name: constr_name, .. name: constr_name,
field_map,
..
} => { } => {
let data_type_key = match &*constructor.tipo { let data_type_key = match &*constructor.tipo {
Type::App { module, name, .. } => DataTypeKey { Type::App { module, name, .. } => DataTypeKey {
@ -1412,7 +1414,34 @@ impl<'a> CodeGenerator<'a> {
.find(|(_, x)| x.name == *constr_name) .find(|(_, x)| x.name == *constr_name)
.unwrap(); .unwrap();
let term = Term::Apply { let mut fields =
Term::Constant(UplcConstant::Data(PlutusData::Array(vec![])));
if let Some(field_map) = field_map.clone() {
for field in field_map
.fields
.iter()
.sorted_by(|item1, item2| item1.1.cmp(item2.1))
.rev()
{
fields = Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::MkCons)
.force_wrap()
.into(),
argument: Term::Var(Name {
text: field.0.clone(),
unique: 0.into(),
})
.into(),
}
.into(),
argument: fields.into(),
};
}
}
let mut term = Term::Apply {
function: Term::Builtin(DefaultFunction::ConstrData).into(), function: Term::Builtin(DefaultFunction::ConstrData).into(),
argument: Term::Apply { argument: Term::Apply {
function: Term::Apply { function: Term::Apply {
@ -1425,14 +1454,32 @@ impl<'a> CodeGenerator<'a> {
.into(), .into(),
} }
.into(), .into(),
argument: Term::Constant(UplcConstant::Data(PlutusData::Array( argument: Term::Apply {
vec![], function: Term::Builtin(DefaultFunction::ListData).into(),
))) argument: fields.into(),
}
.into(), .into(),
} }
.into(), .into(),
}; };
if let Some(field_map) = field_map {
for field in field_map
.fields
.iter()
.sorted_by(|item1, item2| item1.1.cmp(item2.1))
.rev()
{
term = Term::Lambda {
parameter_name: Name {
text: field.0.clone(),
unique: 0.into(),
},
body: term.into(),
};
}
}
arg_stack.push(term); arg_stack.push(term);
} }
} }
@ -1623,19 +1670,58 @@ impl<'a> CodeGenerator<'a> {
let left = arg_stack.pop().unwrap(); let left = arg_stack.pop().unwrap();
let right = arg_stack.pop().unwrap(); let right = arg_stack.pop().unwrap();
let default_builtin = match tipo.deref() {
Type::App { name, .. } => {
if name == "Int" {
Term::Builtin(DefaultFunction::EqualsInteger)
} else if name == "String" {
Term::Builtin(DefaultFunction::EqualsString)
} else if name == "ByteArray" {
Term::Builtin(DefaultFunction::EqualsByteString)
} else {
Term::Builtin(DefaultFunction::EqualsData)
}
}
_ => unreachable!(),
};
let term = match name { let term = match name {
BinOp::And => todo!(), BinOp::And => Term::Apply {
BinOp::Or => todo!(), function: Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::IfThenElse)
.force_wrap()
.into(),
argument: left.into(),
}
.into(),
argument: Term::Delay(right.into()).into(),
}
.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(false)).into())
.into(),
}
.into(),
argument: Term::Delay(right.into()).into(),
}
.force_wrap(),
BinOp::Eq => { BinOp::Eq => {
let default_builtin = match tipo.deref() { match tipo.deref() {
Type::App { name, .. } => { Type::App { name, .. } => {
if name == "Int" { if name == "Bool" {
Term::Builtin(DefaultFunction::EqualsInteger)
} else if name == "String" {
Term::Builtin(DefaultFunction::EqualsString)
} else if name == "ByteArray" {
Term::Builtin(DefaultFunction::EqualsByteString)
} else if name == "Bool" {
let term = Term::Force( let term = Term::Force(
Term::Apply { Term::Apply {
function: Term::Apply { function: Term::Apply {
@ -1685,8 +1771,6 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term); arg_stack.push(term);
return; return;
} else {
Term::Builtin(DefaultFunction::EqualsData)
} }
} }
_ => unreachable!(), _ => unreachable!(),
@ -1701,7 +1785,86 @@ impl<'a> CodeGenerator<'a> {
argument: right.into(), argument: right.into(),
} }
} }
BinOp::NotEq => todo!(), BinOp::NotEq => {
match tipo.deref() {
Type::App { name, .. } => {
if name == "Bool" {
let term = Term::Force(
Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Force(
Term::Builtin(DefaultFunction::IfThenElse)
.into(),
)
.into(),
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);
return;
}
}
_ => unreachable!(),
};
Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::IfThenElse)
.force_wrap()
.into(),
argument: Term::Apply {
function: Term::Apply {
function: default_builtin.into(),
argument: left.into(),
}
.into(),
argument: right.into(),
}
.into(),
}
.into(),
argument: Term::Constant(UplcConstant::Bool(false)).into(),
}
.into(),
argument: Term::Constant(UplcConstant::Bool(true)).into(),
}
}
BinOp::LtInt => Term::Apply { BinOp::LtInt => Term::Apply {
function: Term::Apply { function: Term::Apply {
function: Term::Builtin(DefaultFunction::LessThanInteger).into(), function: Term::Builtin(DefaultFunction::LessThanInteger).into(),
@ -2174,7 +2337,7 @@ impl<'a> CodeGenerator<'a> {
.into(), .into(),
} }
} else if tipo.is_list() { } else if tipo.is_list() {
todo!() unreachable!()
} else { } else {
Term::Apply { Term::Apply {
function: DefaultFunction::EqualsInteger.into(), function: DefaultFunction::EqualsInteger.into(),
@ -2526,6 +2689,7 @@ impl<'a> CodeGenerator<'a> {
IR::Todo { .. } => { IR::Todo { .. } => {
arg_stack.push(Term::Error); arg_stack.push(Term::Error);
} }
IR::Record { .. } => todo!(),
IR::RecordUpdate { .. } => todo!(), IR::RecordUpdate { .. } => todo!(),
IR::Negate { .. } => todo!(), IR::Negate { .. } => todo!(),
} }
@ -2866,7 +3030,10 @@ fn constants_ir(literal: &Constant<Arc<Type>, String>, ir_stack: &mut Vec<IR>, s
constants_ir(element, ir_stack, scope.clone()); constants_ir(element, ir_stack, scope.clone());
} }
} }
Constant::Record { .. } => todo!(), Constant::Record { .. } => {
// ir_stack.push(IR::Record { scope, });
todo!()
}
Constant::ByteArray { bytes, .. } => { Constant::ByteArray { bytes, .. } => {
ir_stack.push(IR::ByteArray { ir_stack.push(IR::ByteArray {
scope, scope,