feat: add tuples and streamline conversion of types to and from data

This commit is contained in:
Kasey White 2022-12-07 04:35:41 -05:00 committed by Lucas
parent d8ff574045
commit 2f7131e9b8
7 changed files with 643 additions and 325 deletions

View File

@ -45,20 +45,16 @@ pub enum Air {
tail: bool,
},
Tail {
scope: Vec<u64>,
name: String,
prev_tail_name: String,
},
ListAccessor {
scope: Vec<u64>,
tipo: Arc<Type>,
names: Vec<String>,
tail: bool,
},
ListExpose {
scope: Vec<u64>,
tipo: Arc<Type>,
tail_head_names: Vec<(String, String)>,
tail: Option<(String, String)>,
},
@ -120,13 +116,6 @@ pub enum Air {
name: String,
},
// Try {
// scope: Vec<u64>,
// tipo: Arc<Type>,
// value: Box<Self>,
// then: Box<Self>,
// pattern: Pattern<PatternConstructor, Arc<Type>>,
// },
When {
scope: Vec<u64>,
tipo: Arc<Type>,
@ -196,13 +185,11 @@ pub enum Air {
// module_alias: String,
// constructor: ModuleValueConstructor,
// },
// Tuple {
// scope: Vec<u64>,
//
// tipo: Arc<Type>,
// elems: Vec<Self>,
// },
Tuple {
scope: Vec<u64>,
tipo: Arc<Type>,
count: usize,
},
// TupleIndex {
// scope: Vec<u64>,
@ -242,7 +229,6 @@ impl Air {
| Air::ByteArray { scope, .. }
| Air::Var { scope, .. }
| Air::List { scope, .. }
| Air::Tail { scope, .. }
| Air::ListAccessor { scope, .. }
| Air::ListExpose { scope, .. }
| Air::Call { scope, .. }
@ -265,6 +251,7 @@ impl Air {
| Air::Fields { scope, .. }
| Air::RecordAccess { scope, .. }
| Air::FieldsExpose { scope, .. }
| Air::Tuple { scope, .. }
| Air::Todo { scope, .. }
| Air::Record { scope, .. }
| Air::RecordUpdate { scope, .. }

View File

@ -135,6 +135,43 @@ impl Type {
}
}
pub fn is_map(&self) -> bool {
match self {
Self::App {
module, name, args, ..
} if "List" == name && module.is_empty() => {
if let Type::Tuple { elems } = &*args[0] {
elems.len() == 2
} else {
false
}
}
Self::Var { tipo } => tipo.borrow().is_map(),
_ => false,
}
}
pub fn is_tuple(&self) -> bool {
matches!(self, Self::Tuple { .. })
}
pub fn get_inner_type(&self) -> Vec<Arc<Type>> {
if self.is_list() {
match self {
Self::App { args, .. } => args.clone(),
Self::Var { tipo } => tipo.borrow().get_inner_type(),
_ => vec![],
}
} else if self.is_tuple() {
match self {
Self::Tuple { elems } => elems.to_vec(),
_ => vec![],
}
} else {
vec![]
}
}
pub fn get_uplc_type(&self) -> UplcType {
if self.is_int() {
UplcType::Integer
@ -144,21 +181,21 @@ impl Type {
UplcType::String
} else if self.is_bool() {
UplcType::Bool
} else if self.is_map() {
UplcType::List(UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()).into())
} else if self.is_list() {
let args_type = match self {
Self::App {
module, name, args, ..
} if "List" == name && module.is_empty() => args[0].clone(),
Self::Var { tipo } => {
if let TypeVar::Link { tipo } = tipo.borrow().clone() {
tipo
UplcType::List(UplcType::Data.into())
} else if self.is_tuple() {
match self {
Self::Tuple { elems } => {
if elems.len() == 2 {
UplcType::Pair(UplcType::Data.into(), UplcType::Data.into())
} else {
todo!()
UplcType::List(UplcType::Data.into())
}
}
_ => todo!(),
};
UplcType::List(Box::new(args_type.get_uplc_type()))
}
} else {
UplcType::Data
}
@ -334,6 +371,20 @@ impl TypeVar {
_ => false,
}
}
pub fn is_map(&self) -> bool {
match self {
Self::Link { tipo } => tipo.is_map(),
_ => false,
}
}
pub fn get_inner_type(&self) -> Vec<Arc<Type>> {
match self {
Self::Link { tipo } => tipo.get_inner_type(),
_ => vec![],
}
}
}
#[derive(Debug, Clone, PartialEq)]

View File

@ -8,7 +8,9 @@ use uplc::{
Constant as UplcConstant, Name, Program, Term, Type as UplcType,
},
builtins::DefaultFunction,
machine::runtime::convert_constr_to_tag,
parser::interner::Interner,
BigInt, Constr, PlutusData,
};
use crate::{
@ -525,7 +527,23 @@ impl<'a> CodeGenerator<'a> {
}
TypedExpr::RecordUpdate { .. } => todo!(),
TypedExpr::Negate { .. } => todo!(),
TypedExpr::Tuple { .. } => todo!(),
TypedExpr::Tuple { elems, tipo, .. } => {
ir_stack.push(Air::Tuple {
scope: scope.clone(),
tipo: tipo.clone(),
count: elems.len(),
});
let mut elems_air = vec![];
for elem in elems {
let mut scope = scope.clone();
scope.push(self.id_gen.next());
self.build_ir(elem, &mut elems_air, scope);
}
ir_stack.append(&mut elems_air);
}
}
}
@ -731,7 +749,7 @@ impl<'a> CodeGenerator<'a> {
pattern_vec: &mut Vec<Air>,
values: &mut Vec<Air>,
clause_properties: ClauseProperties,
_tipo: &Type,
tipo: &Type,
scope: Vec<u64>,
) {
match pattern {
@ -821,12 +839,14 @@ impl<'a> CodeGenerator<'a> {
pattern_vec.push(Air::ListExpose {
scope,
tipo: tipo.clone().into(),
tail_head_names,
tail: Some((tail_var, tail_name)),
});
} else {
pattern_vec.push(Air::ListExpose {
scope,
tipo: tipo.clone().into(),
tail_head_names,
tail: None,
});
@ -1066,13 +1086,12 @@ impl<'a> CodeGenerator<'a> {
pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<Air>,
value_vec: &mut Vec<Air>,
_tipo: &Type,
tipo: &Type,
kind: AssignmentKind,
scope: Vec<u64>,
) {
match pattern {
Pattern::Int { .. } => todo!(),
Pattern::String { .. } => todo!(),
Pattern::Int { .. } | Pattern::String { .. } => unreachable!(),
Pattern::Var { name, .. } => {
pattern_vec.push(Air::Assignment {
name: name.clone(),
@ -1084,12 +1103,14 @@ impl<'a> CodeGenerator<'a> {
}
Pattern::VarUsage { .. } => todo!(),
Pattern::Assign { .. } => todo!(),
Pattern::Discard { .. } => todo!(),
Pattern::Discard { .. } => {
self.pattern_ir(pattern, pattern_vec, value_vec, tipo, scope)
}
list @ Pattern::List { .. } => {
self.pattern_ir(list, pattern_vec, value_vec, scope);
self.pattern_ir(list, pattern_vec, value_vec, tipo, scope);
}
Pattern::Constructor { .. } => {
self.pattern_ir(pattern, pattern_vec, value_vec, scope);
self.pattern_ir(pattern, pattern_vec, value_vec, tipo, scope);
}
Pattern::Tuple { .. } => todo!(),
}
@ -1100,6 +1121,7 @@ impl<'a> CodeGenerator<'a> {
pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>,
pattern_vec: &mut Vec<Air>,
values: &mut Vec<Air>,
tipo: &Type,
scope: Vec<u64>,
) {
match pattern {
@ -1142,7 +1164,13 @@ impl<'a> CodeGenerator<'a> {
name: item_name,
scope: scope.clone(),
});
self.pattern_ir(a, &mut elements_vec, &mut var_vec, scope.clone());
self.pattern_ir(
a,
&mut elements_vec,
&mut var_vec,
&tipo.get_inner_type()[0],
scope.clone(),
);
}
_ => todo!(),
}
@ -1160,6 +1188,7 @@ impl<'a> CodeGenerator<'a> {
names,
tail: tail.is_some(),
scope,
tipo: tipo.clone().into(),
});
pattern_vec.append(values);
@ -1241,6 +1270,7 @@ impl<'a> CodeGenerator<'a> {
),
name: constr_name.clone(),
}],
tipo,
scope.clone(),
);
@ -1305,6 +1335,7 @@ impl<'a> CodeGenerator<'a> {
),
name: constr_name.clone(),
}],
tipo,
scope.clone(),
);
@ -1371,11 +1402,14 @@ impl<'a> CodeGenerator<'a> {
}
Air::Var {
name, constructor, ..
} => match constructor.variant {
ValueConstructorVariant::LocalVariable { .. } => arg_stack.push(Term::Var(Name {
} => {
match constructor.variant {
ValueConstructorVariant::LocalVariable { .. } => {
arg_stack.push(Term::Var(Name {
text: name,
unique: 0.into(),
})),
}))
}
ValueConstructorVariant::ModuleConstant { .. } => {
unreachable!()
}
@ -1416,7 +1450,8 @@ impl<'a> CodeGenerator<'a> {
};
if data_type_key.defined_type == "Bool" {
arg_stack.push(Term::Constant(UplcConstant::Bool(constr_name == "True")));
arg_stack
.push(Term::Constant(UplcConstant::Bool(constr_name == "True")));
} else {
let data_type = self.data_types.get(&data_type_key).unwrap();
let (constr_index, _constr) = data_type
@ -1445,60 +1480,19 @@ impl<'a> CodeGenerator<'a> {
.zip(args_type)
.rev()
{
let arg_to_data = if field.1.as_ref().is_bytearray() {
Term::Apply {
function: Term::Builtin(DefaultFunction::BData).into(),
argument: Term::Var(Name {
text: field.0 .0.clone(),
unique: 0.into(),
})
.into(),
}
} else if field.1.as_ref().is_int() {
Term::Apply {
function: Term::Builtin(DefaultFunction::IData).into(),
argument: Term::Var(Name {
text: field.0 .0.clone(),
unique: 0.into(),
})
.into(),
}
} else if field.1.as_ref().is_list() {
Term::Apply {
function: Term::Builtin(DefaultFunction::ListData).into(),
argument: Term::Var(Name {
text: field.0 .0.clone(),
unique: 0.into(),
})
.into(),
}
} else if field.1.as_ref().is_string() {
Term::Apply {
function: Term::Builtin(DefaultFunction::BData).into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::DecodeUtf8)
.into(),
argument: Term::Var(Name {
text: field.0 .0.clone(),
unique: 0.into(),
})
.into(),
}
.into(),
}
} else {
Term::Var(Name {
text: field.0 .0.clone(),
unique: 0.into(),
})
};
fields = Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::MkCons)
.force_wrap()
.into(),
argument: arg_to_data.into(),
argument: convert_type_to_data(
Term::Var(Name {
text: field.0 .0.clone(),
unique: 0.into(),
}),
field.1,
)
.into(),
}
.into(),
argument: fields.into(),
@ -1538,7 +1532,8 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term);
}
}
},
};
}
Air::Discard { .. } => {
arg_stack.push(Term::Constant(UplcConstant::Unit));
}
@ -1558,15 +1553,12 @@ impl<'a> CodeGenerator<'a> {
}
}
let list_type = match tipo.deref() {
Type::App { args, .. } => &args[0],
_ => unreachable!(),
};
let list_type = tipo.get_inner_type()[0].clone();
if constants.len() == args.len() && !tail {
let list = Term::Constant(UplcConstant::ProtoList(
list_type.get_uplc_type(),
constants,
UplcType::Data,
convert_constants_to_data(constants),
));
arg_stack.push(list);
@ -1574,7 +1566,7 @@ impl<'a> CodeGenerator<'a> {
let mut term = if tail {
arg_stack.pop().unwrap()
} else {
Term::Constant(UplcConstant::ProtoList(list_type.get_uplc_type(), vec![]))
Term::Constant(UplcConstant::ProtoList(UplcType::Data, vec![]))
};
for arg in args {
@ -1584,7 +1576,7 @@ impl<'a> CodeGenerator<'a> {
Term::Builtin(DefaultFunction::MkCons).into(),
)
.into(),
argument: arg.into(),
argument: convert_type_to_data(arg, &list_type).into(),
}
.into(),
argument: term.into(),
@ -1593,9 +1585,9 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term);
}
}
Air::Tail { .. } => todo!(),
Air::ListAccessor { names, tail, .. } => {
Air::ListAccessor {
names, tail, tipo, ..
} => {
let value = arg_stack.pop().unwrap();
let mut term = arg_stack.pop().unwrap();
@ -1621,6 +1613,7 @@ impl<'a> CodeGenerator<'a> {
tail,
current_index,
term,
&tipo.get_inner_type()[0],
)
.into(),
argument: Term::Apply {
@ -1635,11 +1628,14 @@ impl<'a> CodeGenerator<'a> {
.into(),
}
.into(),
argument: Term::Apply {
argument: convert_data_to_type(
Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
.into(),
argument: value.into(),
}
},
&tipo.get_inner_type()[0],
)
.into(),
};
@ -1648,10 +1644,13 @@ impl<'a> CodeGenerator<'a> {
Air::ListExpose {
tail_head_names,
tail,
tipo,
..
} => {
let mut term = arg_stack.pop().unwrap();
let list_type = tipo.get_inner_type()[0].clone();
if let Some((tail_var, tail_name)) = tail {
term = Term::Apply {
function: Term::Lambda {
@ -1683,14 +1682,19 @@ impl<'a> CodeGenerator<'a> {
body: term.into(),
}
.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList).force_wrap().into(),
argument: convert_data_to_type(
Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList)
.force_wrap()
.into(),
argument: Term::Var(Name {
text: tail_var,
unique: 0.into(),
})
.into(),
}
},
&list_type,
)
.into(),
};
}
@ -2391,7 +2395,7 @@ impl<'a> CodeGenerator<'a> {
.into(),
}
} else if tipo.is_list() {
unreachable!()
todo!()
} else {
Term::Apply {
function: DefaultFunction::EqualsInteger.into(),
@ -2483,22 +2487,7 @@ impl<'a> CodeGenerator<'a> {
argument: Term::Constant(UplcConstant::Integer(index.into())).into(),
};
if tipo.is_int() {
term = Term::Apply {
function: Term::Builtin(DefaultFunction::UnIData).into(),
argument: term.into(),
};
} else if tipo.is_bytearray() {
term = Term::Apply {
function: Term::Builtin(DefaultFunction::UnBData).into(),
argument: term.into(),
};
} else if tipo.is_list() {
term = Term::Apply {
function: Term::Builtin(DefaultFunction::UnListData).into(),
argument: term.into(),
};
}
term = convert_data_to_type(term, &tipo);
arg_stack.push(term);
}
@ -2530,40 +2519,6 @@ impl<'a> CodeGenerator<'a> {
unique: 0.into(),
});
let unwrapper = if highest.2.is_int() {
Term::Apply {
function: DefaultFunction::UnIData.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList).force_wrap().into(),
argument: last_prev_tail.into(),
}
.into(),
}
} else if highest.2.is_bytearray() {
Term::Apply {
function: DefaultFunction::UnBData.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList).force_wrap().into(),
argument: last_prev_tail.into(),
}
.into(),
}
} else if highest.2.is_list() {
Term::Apply {
function: DefaultFunction::UnListData.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList).force_wrap().into(),
argument: last_prev_tail.into(),
}
.into(),
}
} else {
Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList).force_wrap().into(),
argument: last_prev_tail.into(),
}
};
body = Term::Apply {
function: Term::Lambda {
parameter_name: Name {
@ -2573,7 +2528,14 @@ impl<'a> CodeGenerator<'a> {
body: body.into(),
}
.into(),
argument: unwrapper.into(),
argument: convert_data_to_type(
Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList).force_wrap().into(),
argument: last_prev_tail.into(),
},
&highest.2,
)
.into(),
};
let mut current_field = None;
@ -2600,47 +2562,15 @@ impl<'a> CodeGenerator<'a> {
if let Some(ref field) = current_field {
if field.0 == index {
let unwrapper = if field.2.is_int() {
Term::Apply {
function: DefaultFunction::UnIData.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList)
.force_wrap()
.into(),
argument: prev_tail.clone().into(),
}
.into(),
}
} else if field.2.is_bytearray() {
Term::Apply {
function: DefaultFunction::UnBData.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList)
.force_wrap()
.into(),
argument: prev_tail.clone().into(),
}
.into(),
}
} else if field.2.is_list() {
Term::Apply {
function: DefaultFunction::UnListData.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList)
.force_wrap()
.into(),
argument: prev_tail.clone().into(),
}
.into(),
}
} else {
let unwrapper = convert_data_to_type(
Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList)
.force_wrap()
.into(),
argument: prev_tail.clone().into(),
}
};
},
&field.2,
);
body = Term::Apply {
function: Term::Lambda {
@ -2740,6 +2670,64 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(body);
}
Air::Tuple { tipo, count, .. } => {
let mut args = vec![];
for _ in 0..count {
let arg = arg_stack.pop().unwrap();
args.push(arg);
}
let mut constants = vec![];
for arg in &args {
if let Term::Constant(c) = arg {
constants.push(c.clone())
}
}
let tuple_sub_types = tipo.get_inner_type();
if constants.len() == args.len() {
let data_constants = convert_constants_to_data(constants);
if count == 2 {
let term = Term::Constant(UplcConstant::ProtoPair(
UplcType::Data,
UplcType::Data,
data_constants[0].clone().into(),
data_constants[1].clone().into(),
));
arg_stack.push(term);
} else {
let term =
Term::Constant(UplcConstant::ProtoList(UplcType::Data, data_constants));
arg_stack.push(term);
}
} else if count == 2 {
let term = Term::Apply {
function: Term::Apply {
function: DefaultFunction::MkPairData.into(),
argument: convert_type_to_data(args[0].clone(), &tuple_sub_types[0])
.into(),
}
.into(),
argument: convert_type_to_data(args[1].clone(), &tuple_sub_types[1]).into(),
};
arg_stack.push(term);
} else {
let mut term = Term::Constant(UplcConstant::ProtoList(UplcType::Data, vec![]));
for (arg, tipo) in args.into_iter().zip(tuple_sub_types.into_iter()) {
term = Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::MkCons).into(),
argument: convert_type_to_data(arg, &tipo).into(),
}
.into(),
argument: term.into(),
};
}
arg_stack.push(term);
}
}
Air::Todo { .. } => {
arg_stack.push(Term::Error);
}
@ -3055,6 +3043,35 @@ impl<'a> CodeGenerator<'a> {
}
}
fn convert_constants_to_data(constants: Vec<UplcConstant>) -> Vec<UplcConstant> {
let mut new_constants = vec![];
for constant in constants {
let constant = match constant {
UplcConstant::Integer(i) => {
UplcConstant::Data(PlutusData::BigInt(BigInt::Int((i).try_into().unwrap())))
}
UplcConstant::ByteString(b) => {
UplcConstant::Data(PlutusData::BoundedBytes(b.try_into().unwrap()))
}
UplcConstant::String(s) => UplcConstant::Data(PlutusData::BoundedBytes(
s.as_bytes().to_vec().try_into().unwrap(),
)),
UplcConstant::Bool(b) => UplcConstant::Data(PlutusData::Constr(Constr {
tag: u64::from(b),
any_constructor: None,
fields: vec![],
})),
UplcConstant::ProtoList(_, _) => todo!(),
UplcConstant::ProtoPair(_, _, _, _) => todo!(),
UplcConstant::Data(_) => todo!(),
_ => unreachable!(),
};
new_constants.push(constant);
}
new_constants
}
fn constants_ir(literal: &Constant<Arc<Type>, String>, ir_stack: &mut Vec<Air>, scope: Vec<u64>) {
match literal {
Constant::Int { value, .. } => {
@ -3149,6 +3166,7 @@ fn list_access_to_uplc(
tail: bool,
current_index: usize,
term: Term<Name>,
tipo: &Type,
) -> Term<Name> {
let (first, names) = names.split_first().unwrap();
@ -3190,14 +3208,21 @@ fn list_access_to_uplc(
.into(),
}
.into(),
argument: Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(),
argument: convert_data_to_type(
Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
.into(),
argument: Term::Var(Name {
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
text: format!(
"tail_index_{}_{}",
current_index, id_list[current_index]
),
unique: 0.into(),
})
.into(),
}
},
&Arc::new(tipo.clone()),
)
.into(),
}
.into(),
@ -3248,6 +3273,7 @@ fn list_access_to_uplc(
tail,
current_index + 1,
term,
tipo,
)
.into(),
argument: Term::Apply {
@ -3436,3 +3462,240 @@ fn rearrange_clauses(
final_clauses
}
fn convert_type_to_data(term: Term<Name>, field_type: &Arc<Type>) -> Term<Name> {
if field_type.is_bytearray() {
Term::Apply {
function: DefaultFunction::BData.into(),
argument: term.into(),
}
} else if field_type.is_int() {
Term::Apply {
function: DefaultFunction::IData.into(),
argument: term.into(),
}
} else if field_type.is_map() {
Term::Apply {
function: DefaultFunction::MapData.into(),
argument: term.into(),
}
} else if field_type.is_list() {
Term::Apply {
function: DefaultFunction::ListData.into(),
argument: term.into(),
}
} else if field_type.is_string() {
Term::Apply {
function: DefaultFunction::BData.into(),
argument: Term::Apply {
function: DefaultFunction::EncodeUtf8.into(),
argument: term.into(),
}
.into(),
}
} else if field_type.is_tuple() {
match field_type.get_uplc_type() {
UplcType::List(_) => Term::Apply {
function: DefaultFunction::ListData.into(),
argument: term.into(),
},
UplcType::Pair(_, _) => Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: "__pair".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: DefaultFunction::ListData.into(),
argument: Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::MkCons)
.force_wrap()
.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::FstPair)
.force_wrap()
.force_wrap()
.into(),
argument: Term::Var(Name {
text: "__pair".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
argument: Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::MkCons)
.force_wrap()
.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::SndPair)
.force_wrap()
.force_wrap()
.into(),
argument: Term::Var(Name {
text: "__pair".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
argument: Term::Constant(UplcConstant::ProtoList(
UplcType::Data,
vec![],
))
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
argument: term.into(),
},
_ => unreachable!(),
}
} else if field_type.is_bool() {
Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::IfThenElse)
.force_wrap()
.into(),
argument: term.into(),
}
.into(),
argument: Term::Constant(UplcConstant::Data(PlutusData::Constr(Constr {
tag: convert_constr_to_tag(1),
any_constructor: None,
fields: vec![],
})))
.into(),
}
.into(),
argument: Term::Constant(UplcConstant::Data(PlutusData::Constr(Constr {
tag: convert_constr_to_tag(0),
any_constructor: None,
fields: vec![],
})))
.into(),
}
} else {
term
}
}
fn convert_data_to_type(term: Term<Name>, field_type: &Arc<Type>) -> Term<Name> {
if field_type.is_int() {
Term::Apply {
function: DefaultFunction::UnIData.into(),
argument: term.into(),
}
} else if field_type.is_bytearray() {
Term::Apply {
function: DefaultFunction::UnBData.into(),
argument: term.into(),
}
} else if field_type.is_map() {
Term::Apply {
function: DefaultFunction::UnMapData.into(),
argument: term.into(),
}
} else if field_type.is_list() {
Term::Apply {
function: DefaultFunction::UnListData.into(),
argument: term.into(),
}
} else if field_type.is_string() {
Term::Apply {
function: DefaultFunction::DecodeUtf8.into(),
argument: Term::Apply {
function: DefaultFunction::UnBData.into(),
argument: term.into(),
}
.into(),
}
} else if field_type.is_tuple() {
match field_type.get_uplc_type() {
UplcType::List(_) => Term::Apply {
function: DefaultFunction::UnListData.into(),
argument: term.into(),
},
UplcType::Pair(_, _) => Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: "__list_data".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: "__tail".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::MkPairData).into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList)
.force_wrap()
.into(),
argument: Term::Var(Name {
text: "__list_data".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList)
.force_wrap()
.into(),
argument: Term::Var(Name {
text: "__tail".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
}
.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::TailList).force_wrap().into(),
argument: Term::Var(Name {
text: "__list_data".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
}
.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::UnListData)
.force_wrap()
.into(),
argument: term.into(),
}
.into(),
},
_ => unreachable!(),
}
} else {
term
}
}

View File

@ -7,7 +7,7 @@ use crate::{
pub mod cost_model;
mod error;
mod runtime;
pub mod runtime;
use cost_model::{ExBudget, StepKind};
pub use error::Error;

View File

@ -853,7 +853,7 @@ impl DefaultFunction {
}
}
fn convert_tag_to_constr(tag: i128) -> i128 {
pub fn convert_tag_to_constr(tag: i128) -> i128 {
if tag < 128 {
tag - 121
} else if (1280..1401).contains(&tag) {
@ -863,7 +863,7 @@ fn convert_tag_to_constr(tag: i128) -> i128 {
}
}
fn convert_constr_to_tag(constr: u64) -> u64 {
pub fn convert_constr_to_tag(constr: u64) -> u64 {
if constr < 7 {
constr + 121
} else if constr < 128 {

View File

@ -18,9 +18,8 @@
(lam
__constr_get_field
[
[
[
(force (builtin ifThenElse))
(lam
x
[
[
(builtin equalsByteString)
@ -35,12 +34,28 @@
]
]
]
(con bytestring #0102)
[
(builtin unBData)
[
[
__constr_get_field
[ __constr_fields_exposer rdmr ]
]
(con integer 0)
]
]
(con bool False)
]
(con bool True)
)
[
[
(builtin mkCons)
[ (builtin bData) (con bytestring #f4) ]
]
[
[ (builtin mkCons) rdmr ]
[ [ (builtin mkCons) datum ] (con listdata []) ]
]
]
]
)
(lam

View File

@ -1,5 +1,7 @@
use sample
pub fn spend(datum: sample.Datum, rdmr: sample.Redeemer, _ctx: Nil) -> Bool {
let x = #(datum, rdmr, #[244])
datum.random == rdmr.signer
}