Fix zero-arg builtins invokations.

There are currently two zero-arg builtins:

  - mkNilData
  - mkNilPairData

  And while they have strictly speaking no arguments, the VM still
  requires that they are called with an extra unit argument applied.
This commit is contained in:
KtorZ 2024-07-27 11:31:40 +02:00 committed by Kasey
parent 1c58da4d86
commit 643e43f8aa
3 changed files with 144 additions and 20 deletions

View File

@ -4066,10 +4066,16 @@ impl<'a> CodeGenerator<'a> {
builtin, builtin,
.. ..
} => { } => {
assert!( if let Some(func) = builtin {
builtin.is_none(), return self.gen_uplc(
"found remaining builtin function {func_name:?} ({builtin:?} declared as a module function in {module:?}" Air::Builtin {
count: 0,
func: *func,
tipo: constructor.tipo,
},
arg_stack,
); );
}
if let Some((names, index, cyclic_name)) = self.cyclic_functions.get(&( if let Some((names, index, cyclic_name)) = self.cyclic_functions.get(&(
FunctionAccessKey { FunctionAccessKey {
@ -4490,9 +4496,13 @@ impl<'a> CodeGenerator<'a> {
term = builder::apply_builtin_forces(term, func.force_count()); term = builder::apply_builtin_forces(term, func.force_count());
if func.arg_is_unit() {
term = term.apply(Term::unit())
} else {
for arg in arg_vec { for arg in arg_vec {
term = term.apply(arg.clone()); term = term.apply(arg.clone());
} }
}
term term
} }

View File

@ -6562,3 +6562,41 @@ fn mk_cons_direct_invoke_3() {
false, false,
) )
} }
#[test]
fn mk_nil_pair_data() {
let src = r#"
use aiken/builtin.{mk_nil_pair_data}
test nil_equals() {
mk_nil_pair_data() == mk_nil_pair_data()
}
"#;
assert_uplc(
src,
Term::equals_data()
.apply(Term::map_data().apply(Term::mk_nil_pair_data().apply(Term::unit())))
.apply(Term::map_data().apply(Term::mk_nil_pair_data().apply(Term::unit()))),
false,
)
}
#[test]
fn mk_nil_list_data() {
let src = r#"
use aiken/builtin.{mk_nil_data}
test nil_equals() {
mk_nil_data() == mk_nil_data()
}
"#;
assert_uplc(
src,
Term::equals_data()
.apply(Term::list_data().apply(Term::mk_nil_data().apply(Term::unit())))
.apply(Term::list_data().apply(Term::mk_nil_data().apply(Term::unit()))),
false,
)
}

View File

@ -1,23 +1,20 @@
use std::{mem::size_of, ops::Deref, rc::Rc}; use super::{
cost_model::{BuiltinCosts, ExBudget},
use num_bigint::BigInt; value::{from_pallas_bigint, to_pallas_bigint},
use num_integer::Integer; Error, Value,
use num_traits::{Signed, Zero}; };
use once_cell::sync::Lazy;
use pallas_primitives::conway::{Language, PlutusData};
use crate::{ use crate::{
ast::{Constant, Data, Type}, ast::{Constant, Data, Type},
builtins::DefaultFunction, builtins::DefaultFunction,
machine::value::integer_log2, machine::value::integer_log2,
plutus_data_to_bytes, plutus_data_to_bytes,
}; };
use num_bigint::BigInt;
use super::{ use num_integer::Integer;
cost_model::{BuiltinCosts, ExBudget}, use num_traits::{Signed, Zero};
value::{from_pallas_bigint, to_pallas_bigint}, use once_cell::sync::Lazy;
Error, Value, use pallas_primitives::conway::{Language, PlutusData};
}; use std::{mem::size_of, ops::Deref, rc::Rc};
static SCALAR_PERIOD: Lazy<BigInt> = Lazy::new(|| { static SCALAR_PERIOD: Lazy<BigInt> = Lazy::new(|| {
BigInt::from_bytes_be( BigInt::from_bytes_be(
@ -111,6 +108,85 @@ impl From<DefaultFunction> for BuiltinRuntime {
} }
impl DefaultFunction { impl DefaultFunction {
pub fn arg_is_unit(&self) -> bool {
match self {
DefaultFunction::MkNilData | DefaultFunction::MkNilPairData => true,
DefaultFunction::AddInteger
| DefaultFunction::SubtractInteger
| DefaultFunction::MultiplyInteger
| DefaultFunction::DivideInteger
| DefaultFunction::QuotientInteger
| DefaultFunction::RemainderInteger
| DefaultFunction::ModInteger
| DefaultFunction::EqualsInteger
| DefaultFunction::LessThanInteger
| DefaultFunction::LessThanEqualsInteger
| DefaultFunction::AppendByteString
| DefaultFunction::ConsByteString
| DefaultFunction::SliceByteString
| DefaultFunction::LengthOfByteString
| DefaultFunction::IndexByteString
| DefaultFunction::EqualsByteString
| DefaultFunction::LessThanByteString
| DefaultFunction::LessThanEqualsByteString
| DefaultFunction::Sha2_256
| DefaultFunction::Sha3_256
| DefaultFunction::Blake2b_224
| DefaultFunction::Blake2b_256
| DefaultFunction::Keccak_256
| DefaultFunction::VerifyEd25519Signature
| DefaultFunction::VerifyEcdsaSecp256k1Signature
| DefaultFunction::VerifySchnorrSecp256k1Signature
| DefaultFunction::AppendString
| DefaultFunction::EqualsString
| DefaultFunction::EncodeUtf8
| DefaultFunction::DecodeUtf8
| DefaultFunction::IfThenElse
| DefaultFunction::ChooseUnit
| DefaultFunction::Trace
| DefaultFunction::FstPair
| DefaultFunction::SndPair
| DefaultFunction::ChooseList
| DefaultFunction::MkCons
| DefaultFunction::HeadList
| DefaultFunction::TailList
| DefaultFunction::NullList
| DefaultFunction::ChooseData
| DefaultFunction::ConstrData
| DefaultFunction::MapData
| DefaultFunction::ListData
| DefaultFunction::IData
| DefaultFunction::BData
| DefaultFunction::UnConstrData
| DefaultFunction::UnMapData
| DefaultFunction::UnListData
| DefaultFunction::UnIData
| DefaultFunction::UnBData
| DefaultFunction::EqualsData
| DefaultFunction::SerialiseData
| DefaultFunction::MkPairData
| DefaultFunction::Bls12_381_G1_Add
| DefaultFunction::Bls12_381_G1_Neg
| DefaultFunction::Bls12_381_G1_ScalarMul
| DefaultFunction::Bls12_381_G1_Equal
| DefaultFunction::Bls12_381_G1_Compress
| DefaultFunction::Bls12_381_G1_Uncompress
| DefaultFunction::Bls12_381_G1_HashToGroup
| DefaultFunction::Bls12_381_G2_Add
| DefaultFunction::Bls12_381_G2_Neg
| DefaultFunction::Bls12_381_G2_ScalarMul
| DefaultFunction::Bls12_381_G2_Equal
| DefaultFunction::Bls12_381_G2_Compress
| DefaultFunction::Bls12_381_G2_Uncompress
| DefaultFunction::Bls12_381_G2_HashToGroup
| DefaultFunction::Bls12_381_MillerLoop
| DefaultFunction::Bls12_381_MulMlResult
| DefaultFunction::Bls12_381_FinalVerify
| DefaultFunction::IntegerToByteString
| DefaultFunction::ByteStringToInteger => false,
}
}
pub fn arity(&self) -> usize { pub fn arity(&self) -> usize {
match self { match self {
DefaultFunction::AddInteger => 2, DefaultFunction::AddInteger => 2,