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: bool,
}, },
Tail {
scope: Vec<u64>,
name: String,
prev_tail_name: String,
},
ListAccessor { ListAccessor {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>,
names: Vec<String>, names: Vec<String>,
tail: bool, tail: bool,
}, },
ListExpose { ListExpose {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>,
tail_head_names: Vec<(String, String)>, tail_head_names: Vec<(String, String)>,
tail: Option<(String, String)>, tail: Option<(String, String)>,
}, },
@ -120,13 +116,6 @@ pub enum Air {
name: String, name: String,
}, },
// Try {
// scope: Vec<u64>,
// tipo: Arc<Type>,
// value: Box<Self>,
// then: Box<Self>,
// pattern: Pattern<PatternConstructor, Arc<Type>>,
// },
When { When {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
@ -196,13 +185,11 @@ pub enum Air {
// module_alias: String, // module_alias: String,
// constructor: ModuleValueConstructor, // constructor: ModuleValueConstructor,
// }, // },
Tuple {
// Tuple { scope: Vec<u64>,
// scope: Vec<u64>, tipo: Arc<Type>,
// count: usize,
// tipo: Arc<Type>, },
// elems: Vec<Self>,
// },
// TupleIndex { // TupleIndex {
// scope: Vec<u64>, // scope: Vec<u64>,
@ -242,7 +229,6 @@ impl Air {
| Air::ByteArray { scope, .. } | Air::ByteArray { scope, .. }
| Air::Var { scope, .. } | Air::Var { scope, .. }
| Air::List { scope, .. } | Air::List { scope, .. }
| Air::Tail { scope, .. }
| Air::ListAccessor { scope, .. } | Air::ListAccessor { scope, .. }
| Air::ListExpose { scope, .. } | Air::ListExpose { scope, .. }
| Air::Call { scope, .. } | Air::Call { scope, .. }
@ -265,6 +251,7 @@ impl Air {
| Air::Fields { scope, .. } | Air::Fields { scope, .. }
| Air::RecordAccess { scope, .. } | Air::RecordAccess { scope, .. }
| Air::FieldsExpose { scope, .. } | Air::FieldsExpose { scope, .. }
| Air::Tuple { scope, .. }
| Air::Todo { scope, .. } | Air::Todo { scope, .. }
| Air::Record { scope, .. } | Air::Record { scope, .. }
| Air::RecordUpdate { 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 { pub fn get_uplc_type(&self) -> UplcType {
if self.is_int() { if self.is_int() {
UplcType::Integer UplcType::Integer
@ -144,21 +181,21 @@ impl Type {
UplcType::String UplcType::String
} else if self.is_bool() { } else if self.is_bool() {
UplcType::Bool UplcType::Bool
} else if self.is_map() {
UplcType::List(UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()).into())
} else if self.is_list() { } else if self.is_list() {
let args_type = match self { UplcType::List(UplcType::Data.into())
Self::App { } else if self.is_tuple() {
module, name, args, .. match self {
} if "List" == name && module.is_empty() => args[0].clone(), Self::Tuple { elems } => {
Self::Var { tipo } => { if elems.len() == 2 {
if let TypeVar::Link { tipo } = tipo.borrow().clone() { UplcType::Pair(UplcType::Data.into(), UplcType::Data.into())
tipo
} else { } else {
todo!() UplcType::List(UplcType::Data.into())
} }
} }
_ => todo!(), _ => todo!(),
}; }
UplcType::List(Box::new(args_type.get_uplc_type()))
} else { } else {
UplcType::Data UplcType::Data
} }
@ -334,6 +371,20 @@ impl TypeVar {
_ => false, _ => 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)] #[derive(Debug, Clone, PartialEq)]

View File

@ -8,7 +8,9 @@ use uplc::{
Constant as UplcConstant, Name, Program, Term, Type as UplcType, Constant as UplcConstant, Name, Program, Term, Type as UplcType,
}, },
builtins::DefaultFunction, builtins::DefaultFunction,
machine::runtime::convert_constr_to_tag,
parser::interner::Interner, parser::interner::Interner,
BigInt, Constr, PlutusData,
}; };
use crate::{ use crate::{
@ -525,7 +527,23 @@ impl<'a> CodeGenerator<'a> {
} }
TypedExpr::RecordUpdate { .. } => todo!(), TypedExpr::RecordUpdate { .. } => todo!(),
TypedExpr::Negate { .. } => 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>, pattern_vec: &mut Vec<Air>,
values: &mut Vec<Air>, values: &mut Vec<Air>,
clause_properties: ClauseProperties, clause_properties: ClauseProperties,
_tipo: &Type, tipo: &Type,
scope: Vec<u64>, scope: Vec<u64>,
) { ) {
match pattern { match pattern {
@ -821,12 +839,14 @@ impl<'a> CodeGenerator<'a> {
pattern_vec.push(Air::ListExpose { pattern_vec.push(Air::ListExpose {
scope, scope,
tipo: tipo.clone().into(),
tail_head_names, tail_head_names,
tail: Some((tail_var, tail_name)), tail: Some((tail_var, tail_name)),
}); });
} else { } else {
pattern_vec.push(Air::ListExpose { pattern_vec.push(Air::ListExpose {
scope, scope,
tipo: tipo.clone().into(),
tail_head_names, tail_head_names,
tail: None, tail: None,
}); });
@ -1066,13 +1086,12 @@ impl<'a> CodeGenerator<'a> {
pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>, pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<Air>, pattern_vec: &mut Vec<Air>,
value_vec: &mut Vec<Air>, value_vec: &mut Vec<Air>,
_tipo: &Type, tipo: &Type,
kind: AssignmentKind, kind: AssignmentKind,
scope: Vec<u64>, scope: Vec<u64>,
) { ) {
match pattern { match pattern {
Pattern::Int { .. } => todo!(), Pattern::Int { .. } | Pattern::String { .. } => unreachable!(),
Pattern::String { .. } => todo!(),
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
pattern_vec.push(Air::Assignment { pattern_vec.push(Air::Assignment {
name: name.clone(), name: name.clone(),
@ -1084,12 +1103,14 @@ impl<'a> CodeGenerator<'a> {
} }
Pattern::VarUsage { .. } => todo!(), Pattern::VarUsage { .. } => todo!(),
Pattern::Assign { .. } => todo!(), Pattern::Assign { .. } => todo!(),
Pattern::Discard { .. } => todo!(), Pattern::Discard { .. } => {
self.pattern_ir(pattern, pattern_vec, value_vec, tipo, scope)
}
list @ Pattern::List { .. } => { list @ Pattern::List { .. } => {
self.pattern_ir(list, pattern_vec, value_vec, scope); self.pattern_ir(list, pattern_vec, value_vec, tipo, scope);
} }
Pattern::Constructor { .. } => { Pattern::Constructor { .. } => {
self.pattern_ir(pattern, pattern_vec, value_vec, scope); self.pattern_ir(pattern, pattern_vec, value_vec, tipo, scope);
} }
Pattern::Tuple { .. } => todo!(), Pattern::Tuple { .. } => todo!(),
} }
@ -1100,6 +1121,7 @@ impl<'a> CodeGenerator<'a> {
pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>, pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>,
pattern_vec: &mut Vec<Air>, pattern_vec: &mut Vec<Air>,
values: &mut Vec<Air>, values: &mut Vec<Air>,
tipo: &Type,
scope: Vec<u64>, scope: Vec<u64>,
) { ) {
match pattern { match pattern {
@ -1142,7 +1164,13 @@ impl<'a> CodeGenerator<'a> {
name: item_name, name: item_name,
scope: scope.clone(), 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!(), _ => todo!(),
} }
@ -1160,6 +1188,7 @@ impl<'a> CodeGenerator<'a> {
names, names,
tail: tail.is_some(), tail: tail.is_some(),
scope, scope,
tipo: tipo.clone().into(),
}); });
pattern_vec.append(values); pattern_vec.append(values);
@ -1241,6 +1270,7 @@ impl<'a> CodeGenerator<'a> {
), ),
name: constr_name.clone(), name: constr_name.clone(),
}], }],
tipo,
scope.clone(), scope.clone(),
); );
@ -1305,6 +1335,7 @@ impl<'a> CodeGenerator<'a> {
), ),
name: constr_name.clone(), name: constr_name.clone(),
}], }],
tipo,
scope.clone(), scope.clone(),
); );
@ -1371,11 +1402,14 @@ impl<'a> CodeGenerator<'a> {
} }
Air::Var { Air::Var {
name, constructor, .. 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, text: name,
unique: 0.into(), unique: 0.into(),
})), }))
}
ValueConstructorVariant::ModuleConstant { .. } => { ValueConstructorVariant::ModuleConstant { .. } => {
unreachable!() unreachable!()
} }
@ -1416,7 +1450,8 @@ impl<'a> CodeGenerator<'a> {
}; };
if data_type_key.defined_type == "Bool" { 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 { } else {
let data_type = self.data_types.get(&data_type_key).unwrap(); let data_type = self.data_types.get(&data_type_key).unwrap();
let (constr_index, _constr) = data_type let (constr_index, _constr) = data_type
@ -1445,60 +1480,19 @@ impl<'a> CodeGenerator<'a> {
.zip(args_type) .zip(args_type)
.rev() .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 { fields = Term::Apply {
function: Term::Apply { function: Term::Apply {
function: Term::Builtin(DefaultFunction::MkCons) function: Term::Builtin(DefaultFunction::MkCons)
.force_wrap() .force_wrap()
.into(), .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(), .into(),
argument: fields.into(), argument: fields.into(),
@ -1538,7 +1532,8 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term); arg_stack.push(term);
} }
} }
}, };
}
Air::Discard { .. } => { Air::Discard { .. } => {
arg_stack.push(Term::Constant(UplcConstant::Unit)); arg_stack.push(Term::Constant(UplcConstant::Unit));
} }
@ -1558,15 +1553,12 @@ impl<'a> CodeGenerator<'a> {
} }
} }
let list_type = match tipo.deref() { let list_type = tipo.get_inner_type()[0].clone();
Type::App { args, .. } => &args[0],
_ => unreachable!(),
};
if constants.len() == args.len() && !tail { if constants.len() == args.len() && !tail {
let list = Term::Constant(UplcConstant::ProtoList( let list = Term::Constant(UplcConstant::ProtoList(
list_type.get_uplc_type(), UplcType::Data,
constants, convert_constants_to_data(constants),
)); ));
arg_stack.push(list); arg_stack.push(list);
@ -1574,7 +1566,7 @@ impl<'a> CodeGenerator<'a> {
let mut term = if tail { let mut term = if tail {
arg_stack.pop().unwrap() arg_stack.pop().unwrap()
} else { } else {
Term::Constant(UplcConstant::ProtoList(list_type.get_uplc_type(), vec![])) Term::Constant(UplcConstant::ProtoList(UplcType::Data, vec![]))
}; };
for arg in args { for arg in args {
@ -1584,7 +1576,7 @@ impl<'a> CodeGenerator<'a> {
Term::Builtin(DefaultFunction::MkCons).into(), Term::Builtin(DefaultFunction::MkCons).into(),
) )
.into(), .into(),
argument: arg.into(), argument: convert_type_to_data(arg, &list_type).into(),
} }
.into(), .into(),
argument: term.into(), argument: term.into(),
@ -1593,9 +1585,9 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term); arg_stack.push(term);
} }
} }
Air::ListAccessor {
Air::Tail { .. } => todo!(), names, tail, tipo, ..
Air::ListAccessor { names, tail, .. } => { } => {
let value = arg_stack.pop().unwrap(); let value = arg_stack.pop().unwrap();
let mut term = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap();
@ -1621,6 +1613,7 @@ impl<'a> CodeGenerator<'a> {
tail, tail,
current_index, current_index,
term, term,
&tipo.get_inner_type()[0],
) )
.into(), .into(),
argument: Term::Apply { argument: Term::Apply {
@ -1635,11 +1628,14 @@ impl<'a> CodeGenerator<'a> {
.into(), .into(),
} }
.into(), .into(),
argument: Term::Apply { argument: convert_data_to_type(
Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()) function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
.into(), .into(),
argument: value.into(), argument: value.into(),
} },
&tipo.get_inner_type()[0],
)
.into(), .into(),
}; };
@ -1648,10 +1644,13 @@ impl<'a> CodeGenerator<'a> {
Air::ListExpose { Air::ListExpose {
tail_head_names, tail_head_names,
tail, tail,
tipo,
.. ..
} => { } => {
let mut term = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap();
let list_type = tipo.get_inner_type()[0].clone();
if let Some((tail_var, tail_name)) = tail { if let Some((tail_var, tail_name)) = tail {
term = Term::Apply { term = Term::Apply {
function: Term::Lambda { function: Term::Lambda {
@ -1683,14 +1682,19 @@ impl<'a> CodeGenerator<'a> {
body: term.into(), body: term.into(),
} }
.into(), .into(),
argument: Term::Apply { argument: convert_data_to_type(
function: Term::Builtin(DefaultFunction::HeadList).force_wrap().into(), Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList)
.force_wrap()
.into(),
argument: Term::Var(Name { argument: Term::Var(Name {
text: tail_var, text: tail_var,
unique: 0.into(), unique: 0.into(),
}) })
.into(), .into(),
} },
&list_type,
)
.into(), .into(),
}; };
} }
@ -2391,7 +2395,7 @@ impl<'a> CodeGenerator<'a> {
.into(), .into(),
} }
} else if tipo.is_list() { } else if tipo.is_list() {
unreachable!() todo!()
} else { } else {
Term::Apply { Term::Apply {
function: DefaultFunction::EqualsInteger.into(), function: DefaultFunction::EqualsInteger.into(),
@ -2483,22 +2487,7 @@ impl<'a> CodeGenerator<'a> {
argument: Term::Constant(UplcConstant::Integer(index.into())).into(), argument: Term::Constant(UplcConstant::Integer(index.into())).into(),
}; };
if tipo.is_int() { term = convert_data_to_type(term, &tipo);
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(),
};
}
arg_stack.push(term); arg_stack.push(term);
} }
@ -2530,40 +2519,6 @@ impl<'a> CodeGenerator<'a> {
unique: 0.into(), 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 { body = Term::Apply {
function: Term::Lambda { function: Term::Lambda {
parameter_name: Name { parameter_name: Name {
@ -2573,7 +2528,14 @@ impl<'a> CodeGenerator<'a> {
body: body.into(), body: body.into(),
} }
.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; let mut current_field = None;
@ -2600,47 +2562,15 @@ impl<'a> CodeGenerator<'a> {
if let Some(ref field) = current_field { if let Some(ref field) = current_field {
if field.0 == index { if field.0 == index {
let unwrapper = if field.2.is_int() { let unwrapper = convert_data_to_type(
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 {
Term::Apply { Term::Apply {
function: Term::Builtin(DefaultFunction::HeadList) function: Term::Builtin(DefaultFunction::HeadList)
.force_wrap() .force_wrap()
.into(), .into(),
argument: prev_tail.clone().into(), argument: prev_tail.clone().into(),
} },
}; &field.2,
);
body = Term::Apply { body = Term::Apply {
function: Term::Lambda { function: Term::Lambda {
@ -2740,6 +2670,64 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(body); 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 { .. } => { Air::Todo { .. } => {
arg_stack.push(Term::Error); 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>) { fn constants_ir(literal: &Constant<Arc<Type>, String>, ir_stack: &mut Vec<Air>, scope: Vec<u64>) {
match literal { match literal {
Constant::Int { value, .. } => { Constant::Int { value, .. } => {
@ -3149,6 +3166,7 @@ fn list_access_to_uplc(
tail: bool, tail: bool,
current_index: usize, current_index: usize,
term: Term<Name>, term: Term<Name>,
tipo: &Type,
) -> Term<Name> { ) -> Term<Name> {
let (first, names) = names.split_first().unwrap(); let (first, names) = names.split_first().unwrap();
@ -3190,14 +3208,21 @@ fn list_access_to_uplc(
.into(), .into(),
} }
.into(), .into(),
argument: Term::Apply { argument: convert_data_to_type(
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(), Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
.into(),
argument: Term::Var(Name { 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(), unique: 0.into(),
}) })
.into(), .into(),
} },
&Arc::new(tipo.clone()),
)
.into(), .into(),
} }
.into(), .into(),
@ -3248,6 +3273,7 @@ fn list_access_to_uplc(
tail, tail,
current_index + 1, current_index + 1,
term, term,
tipo,
) )
.into(), .into(),
argument: Term::Apply { argument: Term::Apply {
@ -3436,3 +3462,240 @@ fn rearrange_clauses(
final_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; pub mod cost_model;
mod error; mod error;
mod runtime; pub mod runtime;
use cost_model::{ExBudget, StepKind}; use cost_model::{ExBudget, StepKind};
pub use error::Error; 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 { if tag < 128 {
tag - 121 tag - 121
} else if (1280..1401).contains(&tag) { } 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 { if constr < 7 {
constr + 121 constr + 121
} else if constr < 128 { } else if constr < 128 {

View File

@ -18,9 +18,8 @@
(lam (lam
__constr_get_field __constr_get_field
[ [
[ (lam
[ x
(force (builtin ifThenElse))
[ [
[ [
(builtin equalsByteString) (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 (lam

View File

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