feat: add ability to downcast void to data

This commit is contained in:
Kasey White 2023-02-12 18:53:02 -05:00 committed by Lucas
parent 4c838defd1
commit 765ceefd38
3 changed files with 140 additions and 7 deletions

View File

@ -4,7 +4,7 @@ use indexmap::{IndexMap, IndexSet};
use itertools::Itertools; use itertools::Itertools;
use uplc::{ use uplc::{
ast::{ ast::{
builder::{apply_wrap, delayed_choose_list, if_else}, builder::{apply_wrap, delayed_choose_list, delayed_if_else, if_else},
Constant as UplcConstant, Name, Term, Type as UplcType, Constant as UplcConstant, Name, Term, Type as UplcType,
}, },
builtins::DefaultFunction, builtins::DefaultFunction,
@ -190,6 +190,18 @@ pub fn convert_type_to_data(term: Term<Name>, field_type: &Arc<Type>) -> Term<Na
apply_wrap(DefaultFunction::BData.into(), term) apply_wrap(DefaultFunction::BData.into(), term)
} else if field_type.is_int() { } else if field_type.is_int() {
apply_wrap(DefaultFunction::IData.into(), term) apply_wrap(DefaultFunction::IData.into(), term)
} else if field_type.is_void() {
apply_wrap(
apply_wrap(Term::Builtin(DefaultFunction::ChooseUnit).force_wrap(), term),
Term::Constant(
UplcConstant::Data(PlutusData::Constr(Constr {
tag: convert_constr_to_tag(0).unwrap(),
any_constructor: None,
fields: vec![],
}))
.into(),
),
)
} else if field_type.is_map() { } else if field_type.is_map() {
apply_wrap(DefaultFunction::MapData.into(), term) apply_wrap(DefaultFunction::MapData.into(), term)
} else if field_type.is_string() { } else if field_type.is_string() {
@ -279,6 +291,23 @@ pub fn convert_data_to_type(term: Term<Name>, field_type: &Arc<Type>) -> Term<Na
apply_wrap(DefaultFunction::UnIData.into(), term) apply_wrap(DefaultFunction::UnIData.into(), term)
} else if field_type.is_bytearray() { } else if field_type.is_bytearray() {
apply_wrap(DefaultFunction::UnBData.into(), term) apply_wrap(DefaultFunction::UnBData.into(), term)
} else if field_type.is_void() {
delayed_if_else(
apply_wrap(
apply_wrap(
DefaultFunction::EqualsInteger.into(),
Term::Constant(UplcConstant::Integer(0.into()).into()),
),
apply_wrap(
Term::Builtin(DefaultFunction::FstPair)
.force_wrap()
.force_wrap(),
apply_wrap(DefaultFunction::UnConstrData.into(), term),
),
),
Term::Constant(UplcConstant::Unit.into()),
Term::Error,
)
} else if field_type.is_map() { } else if field_type.is_map() {
apply_wrap(DefaultFunction::UnMapData.into(), term) apply_wrap(DefaultFunction::UnMapData.into(), term)
} else if field_type.is_string() { } else if field_type.is_string() {
@ -1289,7 +1318,11 @@ pub fn convert_constants_to_data(constants: Vec<Rc<UplcConstant>>) -> Vec<UplcCo
)]))) )])))
} }
d @ UplcConstant::Data(_) => d.clone(), d @ UplcConstant::Data(_) => d.clone(),
_ => unreachable!(), UplcConstant::Unit => UplcConstant::Data(PlutusData::Constr(Constr {
tag: convert_constr_to_tag(0).unwrap(),
any_constructor: None,
fields: vec![],
})),
}; };
new_constants.push(constant); new_constants.push(constant);
} }

View File

@ -253,12 +253,22 @@ impl<'a> CodeGenerator<'a> {
count: args.len(), count: args.len(),
}); });
for arg in args { if let Some(fun_arg_types) = fun.tipo().arg_types() {
let mut scope = scope.clone(); for (arg, func_type) in args.iter().zip(fun_arg_types) {
scope.push(self.id_gen.next()); let mut scope = scope.clone();
self.build_ir(&arg.value, ir_stack, scope); scope.push(self.id_gen.next());
if func_type.is_data() && !arg.value.tipo().is_data() {
ir_stack.push(Air::WrapData {
scope: scope.clone(),
tipo: arg.value.tipo(),
})
}
self.build_ir(&arg.value, ir_stack, scope);
}
return;
} }
return;
} }
} }
} }

View File

@ -1,7 +1,16 @@
use aiken/bytearray use aiken/bytearray
use aiken/dict
use aiken/hash.{Hash, Sha2_256, sha2_256} use aiken/hash.{Hash, Sha2_256, sha2_256}
use aiken/interval.{Interval, IntervalBound, PositiveInfinity}
use aiken/list use aiken/list
use aiken/string use aiken/string
use aiken/transaction.{
InlineDatum, Input, Output, OutputReference, Transaction, TransactionId,
}
use aiken/transaction/credential.{
Address, PublicKeyCredential, ScriptCredential, StakeCredential,
}
use aiken/transaction/value
// MerkleTree in Aiken (ported from: https://github.com/input-output-hk/hydra/blob/master/plutus-merkle-tree/src/Plutus/MerkleTree.hs) // MerkleTree in Aiken (ported from: https://github.com/input-output-hk/hydra/blob/master/plutus-merkle-tree/src/Plutus/MerkleTree.hs)
@ -64,3 +73,84 @@ test foo() {
let mt = from_list(items) let mt = from_list(items)
size(mt) == 3 size(mt) == 3
} }
// const keyhash = #"010203040506"
// const scripthash = #"060504030201"
// pub fn keyhash_address(with_stake_credential: Option<StakeCredential>) {
// Address {
// payment_credential: PublicKeyCredential(keyhash),
// stake_credential: with_stake_credential,
// }
// }
// pub fn scripthash_address(with_stake_credential: Option<StakeCredential>) {
// Address {
// payment_credential: ScriptCredential(scripthash),
// stake_credential: with_stake_credential,
// }
// }
// type SampleData {
// a: Int,
// b: ByteArray,
// }
// pub fn tx_1() -> Transaction {
// let sample_datum = SampleData { a: 1, b: #"01" }
// // let sample_data: Data = sample_datum
// let tx =
// Transaction {
// inputs: [
// Input {
// output_reference: OutputReference {
// transaction_id: TransactionId { hash: #"" },
// output_index: 0,
// },
// output: Output {
// address: scripthash_address(None),
// value: value.zero(),
// datum: InlineDatum(sample_datum),
// reference_script: None,
// },
// },
// ],
// reference_inputs: [],
// outputs: [
// Output {
// address: keyhash_address(None),
// value: value.from_lovelace(10000),
// datum: InlineDatum(sample_datum),
// reference_script: None,
// },
// ],
// fee: value.zero(),
// mint: value.from_asset(#"000000", #"00", -1),
// certificates: [],
// withdrawals: dict.new(),
// validity_range: Interval {
// lower_bound: IntervalBound {
// bound_type: PositiveInfinity,
// is_inclusive: True,
// },
// upper_bound: IntervalBound {
// bound_type: PositiveInfinity,
// is_inclusive: True,
// },
// },
// extra_signatories: [keyhash],
// redeemers: dict.new(),
// datums: dict.new(),
// id: TransactionId { hash: #"" },
// }
// tx
// }
// test some_test2() {
// tx_1() == tx_1()
// }
test some_test1() {
InlineDatum(Void) == InlineDatum(Void)
}