Merge pull request #356 from aiken-lang/big_int
Upgrade Term::Constant to use BigInt
This commit is contained in:
commit
bf15fece57
|
@ -1380,6 +1380,17 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.45"
|
version = "0.1.45"
|
||||||
|
@ -2657,6 +2668,9 @@ dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"itertools",
|
"itertools",
|
||||||
"k256",
|
"k256",
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
"pallas-addresses",
|
"pallas-addresses",
|
||||||
"pallas-codec",
|
"pallas-codec",
|
||||||
"pallas-crypto",
|
"pallas-crypto",
|
||||||
|
|
|
@ -8,8 +8,11 @@ use uplc::{
|
||||||
Constant as UplcConstant, Name, Term, Type as UplcType,
|
Constant as UplcConstant, Name, Term, Type as UplcType,
|
||||||
},
|
},
|
||||||
builtins::DefaultFunction,
|
builtins::DefaultFunction,
|
||||||
machine::runtime::{convert_constr_to_tag, ANY_TAG},
|
machine::{
|
||||||
BigInt, Constr, KeyValuePairs, PlutusData,
|
runtime::{convert_constr_to_tag, ANY_TAG},
|
||||||
|
to_pallas_bigint,
|
||||||
|
},
|
||||||
|
Constr, KeyValuePairs, PlutusData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -332,7 +335,7 @@ pub fn convert_data_to_type(term: Term<Name>, field_type: &Arc<Type>) -> Term<Na
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
DefaultFunction::EqualsInteger.into(),
|
DefaultFunction::EqualsInteger.into(),
|
||||||
Term::Constant(UplcConstant::Integer(1).into()),
|
Term::Constant(UplcConstant::Integer(1.into()).into()),
|
||||||
),
|
),
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
Term::Builtin(DefaultFunction::FstPair)
|
Term::Builtin(DefaultFunction::FstPair)
|
||||||
|
@ -998,9 +1001,7 @@ pub fn convert_constants_to_data(constants: Vec<Rc<UplcConstant>>) -> Vec<UplcCo
|
||||||
let mut new_constants = vec![];
|
let mut new_constants = vec![];
|
||||||
for constant in constants {
|
for constant in constants {
|
||||||
let constant = match constant.as_ref() {
|
let constant = match constant.as_ref() {
|
||||||
UplcConstant::Integer(i) => {
|
UplcConstant::Integer(i) => UplcConstant::Data(PlutusData::BigInt(to_pallas_bigint(i))),
|
||||||
UplcConstant::Data(PlutusData::BigInt(BigInt::Int((*i).try_into().unwrap())))
|
|
||||||
}
|
|
||||||
UplcConstant::ByteString(b) => {
|
UplcConstant::ByteString(b) => {
|
||||||
UplcConstant::Data(PlutusData::BoundedBytes(b.clone().try_into().unwrap()))
|
UplcConstant::Data(PlutusData::BoundedBytes(b.clone().try_into().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -4417,7 +4417,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
DefaultFunction::EqualsInteger.into(),
|
DefaultFunction::EqualsInteger.into(),
|
||||||
Term::Constant(UplcConstant::Integer(constr_index as i128).into()),
|
Term::Constant(UplcConstant::Integer(constr_index.into()).into()),
|
||||||
),
|
),
|
||||||
constr_index_exposer(constr),
|
constr_index_exposer(constr),
|
||||||
),
|
),
|
||||||
|
@ -4975,7 +4975,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
term = apply_wrap(
|
term = apply_wrap(
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
DefaultFunction::ConstrData.into(),
|
DefaultFunction::ConstrData.into(),
|
||||||
Term::Constant(UplcConstant::Integer(constr_index as i128).into()),
|
Term::Constant(UplcConstant::Integer(constr_index.into()).into()),
|
||||||
),
|
),
|
||||||
term,
|
term,
|
||||||
);
|
);
|
||||||
|
@ -5234,7 +5234,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
term = apply_wrap(
|
term = apply_wrap(
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
Term::Builtin(DefaultFunction::ConstrData),
|
Term::Builtin(DefaultFunction::ConstrData),
|
||||||
Term::Constant(UplcConstant::Integer(0).into()),
|
Term::Constant(UplcConstant::Integer(0.into()).into()),
|
||||||
),
|
),
|
||||||
term,
|
term,
|
||||||
);
|
);
|
||||||
|
@ -5342,7 +5342,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
UnOp::Negate => apply_wrap(
|
UnOp::Negate => apply_wrap(
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
DefaultFunction::SubtractInteger.into(),
|
DefaultFunction::SubtractInteger.into(),
|
||||||
Term::Constant(UplcConstant::Integer(0).into()),
|
Term::Constant(UplcConstant::Integer(0.into()).into()),
|
||||||
),
|
),
|
||||||
value,
|
value,
|
||||||
),
|
),
|
||||||
|
@ -5391,7 +5391,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
),
|
),
|
||||||
term,
|
term,
|
||||||
),
|
),
|
||||||
Term::Constant(UplcConstant::Integer(tuple_index as i128).into()),
|
Term::Constant(UplcConstant::Integer(tuple_index.into()).into()),
|
||||||
),
|
),
|
||||||
&tipo.get_inner_types()[tuple_index],
|
&tipo.get_inner_types()[tuple_index],
|
||||||
);
|
);
|
||||||
|
|
|
@ -33,6 +33,9 @@ itertools = "0.10.5"
|
||||||
indexmap = "1.9.2"
|
indexmap = "1.9.2"
|
||||||
secp256k1 = { version = "0.26.0", optional = true }
|
secp256k1 = { version = "0.26.0", optional = true }
|
||||||
k256 = { version = "0.12.0", optional = true }
|
k256 = { version = "0.12.0", optional = true }
|
||||||
|
num-bigint = "0.4.3"
|
||||||
|
num-traits = "0.2.15"
|
||||||
|
num-integer = "0.1.45"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::{
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use num_bigint::BigInt;
|
||||||
use serde::{
|
use serde::{
|
||||||
self,
|
self,
|
||||||
de::{self, Deserialize, Deserializer, MapAccess, Visitor},
|
de::{self, Deserialize, Deserializer, MapAccess, Visitor},
|
||||||
|
@ -228,7 +229,7 @@ where
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Constant {
|
pub enum Constant {
|
||||||
// tag: 0
|
// tag: 0
|
||||||
Integer(i128),
|
Integer(BigInt),
|
||||||
// tag: 1
|
// tag: 1
|
||||||
ByteString(Vec<u8>),
|
ByteString(Vec<u8>),
|
||||||
// tag: 2
|
// tag: 2
|
||||||
|
|
|
@ -391,6 +391,9 @@ impl Encode for Constant {
|
||||||
match self {
|
match self {
|
||||||
Constant::Integer(i) => {
|
Constant::Integer(i) => {
|
||||||
encode_constant(&[0], e)?;
|
encode_constant(&[0], e)?;
|
||||||
|
|
||||||
|
let i: i128 = i.try_into().unwrap();
|
||||||
|
|
||||||
i.encode(e)?;
|
i.encode(e)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +447,11 @@ impl Encode for Constant {
|
||||||
|
|
||||||
fn encode_constant_value(x: &Constant, e: &mut Encoder) -> Result<(), en::Error> {
|
fn encode_constant_value(x: &Constant, e: &mut Encoder) -> Result<(), en::Error> {
|
||||||
match x {
|
match x {
|
||||||
Constant::Integer(x) => x.encode(e),
|
Constant::Integer(x) => {
|
||||||
|
let x: i128 = x.try_into().unwrap();
|
||||||
|
|
||||||
|
x.encode(e)
|
||||||
|
}
|
||||||
Constant::ByteString(b) => b.encode(e),
|
Constant::ByteString(b) => b.encode(e),
|
||||||
Constant::String(s) => s.encode(e),
|
Constant::String(s) => s.encode(e),
|
||||||
Constant::Unit => Ok(()),
|
Constant::Unit => Ok(()),
|
||||||
|
@ -491,7 +498,7 @@ fn encode_type(typ: &Type, bytes: &mut Vec<u8>) {
|
||||||
impl<'b> Decode<'b> for Constant {
|
impl<'b> Decode<'b> for Constant {
|
||||||
fn decode(d: &mut Decoder) -> Result<Self, de::Error> {
|
fn decode(d: &mut Decoder) -> Result<Self, de::Error> {
|
||||||
match &decode_constant(d)?[..] {
|
match &decode_constant(d)?[..] {
|
||||||
[0] => Ok(Constant::Integer(i128::decode(d)?)),
|
[0] => Ok(Constant::Integer(i128::decode(d)?.into())),
|
||||||
[1] => Ok(Constant::ByteString(Vec::<u8>::decode(d)?)),
|
[1] => Ok(Constant::ByteString(Vec::<u8>::decode(d)?)),
|
||||||
[2] => Ok(Constant::String(String::decode(d)?)),
|
[2] => Ok(Constant::String(String::decode(d)?)),
|
||||||
[3] => Ok(Constant::Unit),
|
[3] => Ok(Constant::Unit),
|
||||||
|
@ -534,7 +541,7 @@ impl<'b> Decode<'b> for Constant {
|
||||||
|
|
||||||
fn decode_constant_value(typ: Rc<Type>, d: &mut Decoder) -> Result<Constant, de::Error> {
|
fn decode_constant_value(typ: Rc<Type>, d: &mut Decoder) -> Result<Constant, de::Error> {
|
||||||
match typ.as_ref() {
|
match typ.as_ref() {
|
||||||
Type::Integer => Ok(Constant::Integer(i128::decode(d)?)),
|
Type::Integer => Ok(Constant::Integer(i128::decode(d)?.into())),
|
||||||
Type::ByteString => Ok(Constant::ByteString(Vec::<u8>::decode(d)?)),
|
Type::ByteString => Ok(Constant::ByteString(Vec::<u8>::decode(d)?)),
|
||||||
Type::String => Ok(Constant::String(String::decode(d)?)),
|
Type::String => Ok(Constant::String(String::decode(d)?)),
|
||||||
Type::Unit => Ok(Constant::Unit),
|
Type::Unit => Ok(Constant::Unit),
|
||||||
|
@ -813,7 +820,7 @@ mod test {
|
||||||
fn flat_encode_integer() {
|
fn flat_encode_integer() {
|
||||||
let program = Program::<Name> {
|
let program = Program::<Name> {
|
||||||
version: (11, 22, 33),
|
version: (11, 22, 33),
|
||||||
term: Term::Constant(Constant::Integer(11).into()),
|
term: Term::Constant(Constant::Integer(11.into()).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let expected_bytes = vec![
|
let expected_bytes = vec![
|
||||||
|
@ -833,8 +840,8 @@ mod test {
|
||||||
Constant::ProtoList(
|
Constant::ProtoList(
|
||||||
Type::List(Type::Integer.into()),
|
Type::List(Type::Integer.into()),
|
||||||
vec![
|
vec![
|
||||||
Constant::ProtoList(Type::Integer, vec![Constant::Integer(7)]),
|
Constant::ProtoList(Type::Integer, vec![Constant::Integer(7.into())]),
|
||||||
Constant::ProtoList(Type::Integer, vec![Constant::Integer(5)]),
|
Constant::ProtoList(Type::Integer, vec![Constant::Integer(5.into())]),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -862,11 +869,11 @@ mod test {
|
||||||
Constant::ProtoPair(
|
Constant::ProtoPair(
|
||||||
Type::Integer,
|
Type::Integer,
|
||||||
Type::Bool,
|
Type::Bool,
|
||||||
Constant::Integer(11).into(),
|
Constant::Integer(11.into()).into(),
|
||||||
Constant::Bool(true).into(),
|
Constant::Bool(true).into(),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
Constant::Integer(11).into(),
|
Constant::Integer(11.into()).into(),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
|
@ -895,8 +902,8 @@ mod test {
|
||||||
Constant::ProtoList(
|
Constant::ProtoList(
|
||||||
Type::List(Type::Integer.into()),
|
Type::List(Type::Integer.into()),
|
||||||
vec![
|
vec![
|
||||||
Constant::ProtoList(Type::Integer, vec![Constant::Integer(7)]),
|
Constant::ProtoList(Type::Integer, vec![Constant::Integer(7.into())]),
|
||||||
Constant::ProtoList(Type::Integer, vec![Constant::Integer(5)]),
|
Constant::ProtoList(Type::Integer, vec![Constant::Integer(5.into())]),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -924,11 +931,11 @@ mod test {
|
||||||
Constant::ProtoPair(
|
Constant::ProtoPair(
|
||||||
Type::Integer,
|
Type::Integer,
|
||||||
Type::Bool,
|
Type::Bool,
|
||||||
Constant::Integer(11).into(),
|
Constant::Integer(11.into()).into(),
|
||||||
Constant::Bool(true).into(),
|
Constant::Bool(true).into(),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
Constant::Integer(11).into(),
|
Constant::Integer(11.into()).into(),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
|
@ -947,7 +954,7 @@ mod test {
|
||||||
|
|
||||||
let expected_program = Program {
|
let expected_program = Program {
|
||||||
version: (11, 22, 33),
|
version: (11, 22, 33),
|
||||||
term: Term::Constant(Constant::Integer(11).into()),
|
term: Term::Constant(Constant::Integer(11.into()).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let actual_program: Program<Name> = Program::unflat(&bytes).unwrap();
|
let actual_program: Program<Name> = Program::unflat(&bytes).unwrap();
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use num_traits::sign::Signed;
|
||||||
use std::{collections::VecDeque, ops::Deref, rc::Rc};
|
use std::{collections::VecDeque, ops::Deref, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -11,7 +12,8 @@ pub mod runtime;
|
||||||
|
|
||||||
use cost_model::{ExBudget, StepKind};
|
use cost_model::{ExBudget, StepKind};
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
use pallas_primitives::babbage::{BigInt, Language, PlutusData};
|
use num_bigint::BigInt;
|
||||||
|
use pallas_primitives::babbage::{self as pallas, Language, PlutusData};
|
||||||
|
|
||||||
use self::{cost_model::CostModel, runtime::BuiltinRuntime};
|
use self::{cost_model::CostModel, runtime::BuiltinRuntime};
|
||||||
|
|
||||||
|
@ -531,6 +533,37 @@ pub enum Value {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn integer_log2(i: BigInt) -> i64 {
|
||||||
|
let (_, bytes) = i.to_bytes_be();
|
||||||
|
match bytes.first() {
|
||||||
|
None => unreachable!("empty number?"),
|
||||||
|
Some(u) => (8 - u.leading_zeros() - 1) as i64 + 8 * (bytes.len() - 1) as i64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_pallas_bigint(n: &pallas::BigInt) -> BigInt {
|
||||||
|
match n {
|
||||||
|
pallas::BigInt::Int(i) => i128::from(*i).into(),
|
||||||
|
pallas::BigInt::BigUInt(bytes) => BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes),
|
||||||
|
pallas::BigInt::BigNInt(bytes) => BigInt::from_bytes_be(num_bigint::Sign::Minus, bytes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_pallas_bigint(n: &BigInt) -> pallas::BigInt {
|
||||||
|
if n.bits() <= 64 {
|
||||||
|
let regular_int: i64 = n.try_into().unwrap();
|
||||||
|
let pallas_int: pallas_codec::utils::Int = regular_int.into();
|
||||||
|
|
||||||
|
pallas::BigInt::Int(pallas_int)
|
||||||
|
} else if n.is_positive() {
|
||||||
|
let (_, bytes) = n.to_bytes_be();
|
||||||
|
pallas::BigInt::BigUInt(bytes.into())
|
||||||
|
} else {
|
||||||
|
let (_, bytes) = n.to_bytes_be();
|
||||||
|
pallas::BigInt::BigNInt(bytes.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn is_integer(&self) -> bool {
|
pub fn is_integer(&self) -> bool {
|
||||||
matches!(self, Value::Con(i) if matches!(i.as_ref(), Constant::Integer(_)))
|
matches!(self, Value::Con(i) if matches!(i.as_ref(), Constant::Integer(_)))
|
||||||
|
@ -545,10 +578,10 @@ impl Value {
|
||||||
match self {
|
match self {
|
||||||
Value::Con(c) => match c.as_ref() {
|
Value::Con(c) => match c.as_ref() {
|
||||||
Constant::Integer(i) => {
|
Constant::Integer(i) => {
|
||||||
if *i == 0 {
|
if *i == 0.into() {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
((i.abs() as f64).log2().floor() as i64 / 64) + 1
|
(integer_log2(i.abs()) / 64) + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Constant::ByteString(b) => {
|
Constant::ByteString(b) => {
|
||||||
|
@ -607,12 +640,9 @@ impl Value {
|
||||||
stack = new_stack;
|
stack = new_stack;
|
||||||
}
|
}
|
||||||
PlutusData::BigInt(i) => {
|
PlutusData::BigInt(i) => {
|
||||||
if let BigInt::Int(g) = i {
|
let i = from_pallas_bigint(i);
|
||||||
let numb: i128 = (*g).try_into().unwrap();
|
|
||||||
total += Value::Con(Constant::Integer(numb).into()).to_ex_mem();
|
total += Value::Con(Constant::Integer(i).into()).to_ex_mem();
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
PlutusData::BoundedBytes(b) => {
|
PlutusData::BoundedBytes(b) => {
|
||||||
let byte_string: Vec<u8> = b.deref().clone();
|
let byte_string: Vec<u8> = b.deref().clone();
|
||||||
|
@ -730,3 +760,234 @@ impl From<&Constant> for Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use num_bigint::BigInt;
|
||||||
|
|
||||||
|
use super::{cost_model::ExBudget, integer_log2, Value};
|
||||||
|
use crate::{
|
||||||
|
ast::{Constant, NamedDeBruijn, Program, Term},
|
||||||
|
builtins::DefaultFunction,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_big_ints() {
|
||||||
|
let program: Program<NamedDeBruijn> = Program {
|
||||||
|
version: (0, 0, 0),
|
||||||
|
term: Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::AddInteger).into(),
|
||||||
|
argument: Term::Constant(Constant::Integer(i128::MAX.into()).into()).into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Constant(Constant::Integer(i128::MAX.into()).into()).into(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let (eval_result, _, _) = program.eval(ExBudget::default());
|
||||||
|
|
||||||
|
let term = eval_result.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
term,
|
||||||
|
Term::Constant(
|
||||||
|
Constant::Integer(
|
||||||
|
Into::<BigInt>::into(i128::MAX) + Into::<BigInt>::into(i128::MAX)
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn divide_integer() {
|
||||||
|
let make_program = |fun: DefaultFunction, n: i32, m: i32| Program::<NamedDeBruijn> {
|
||||||
|
version: (0, 0, 0),
|
||||||
|
term: Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Builtin(fun).into(),
|
||||||
|
argument: Term::Constant(Constant::Integer(n.into()).into()).into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Constant(Constant::Integer(m.into()).into()).into(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let test_data = vec![
|
||||||
|
(DefaultFunction::DivideInteger, 8, 3, 2),
|
||||||
|
(DefaultFunction::DivideInteger, 8, -3, -3),
|
||||||
|
(DefaultFunction::DivideInteger, -8, 3, -3),
|
||||||
|
(DefaultFunction::DivideInteger, -8, -3, 2),
|
||||||
|
(DefaultFunction::QuotientInteger, 8, 3, 2),
|
||||||
|
(DefaultFunction::QuotientInteger, 8, -3, -2),
|
||||||
|
(DefaultFunction::QuotientInteger, -8, 3, -2),
|
||||||
|
(DefaultFunction::QuotientInteger, -8, -3, 2),
|
||||||
|
(DefaultFunction::RemainderInteger, 8, 3, 2),
|
||||||
|
(DefaultFunction::RemainderInteger, 8, -3, 2),
|
||||||
|
(DefaultFunction::RemainderInteger, -8, 3, -2),
|
||||||
|
(DefaultFunction::RemainderInteger, -8, -3, -2),
|
||||||
|
(DefaultFunction::ModInteger, 8, 3, 2),
|
||||||
|
(DefaultFunction::ModInteger, 8, -3, -1),
|
||||||
|
(DefaultFunction::ModInteger, -8, 3, 1),
|
||||||
|
(DefaultFunction::ModInteger, -8, -3, -2),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (fun, n, m, result) in test_data {
|
||||||
|
let (eval_result, _, _) = make_program(fun, n, m).eval(ExBudget::default());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
eval_result.unwrap(),
|
||||||
|
Term::Constant(Constant::Integer(result.into()).into())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn to_ex_mem_bigint() {
|
||||||
|
let value = Value::Con(Constant::Integer(1.into()).into());
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 1);
|
||||||
|
|
||||||
|
let value = Value::Con(Constant::Integer(42.into()).into());
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 1);
|
||||||
|
|
||||||
|
let value = Value::Con(
|
||||||
|
Constant::Integer(BigInt::parse_bytes("18446744073709551615".as_bytes(), 10).unwrap())
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 1);
|
||||||
|
|
||||||
|
let value = Value::Con(
|
||||||
|
Constant::Integer(
|
||||||
|
BigInt::parse_bytes("999999999999999999999999999999".as_bytes(), 10).unwrap(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 2);
|
||||||
|
|
||||||
|
let value = Value::Con(
|
||||||
|
Constant::Integer(
|
||||||
|
BigInt::parse_bytes("170141183460469231731687303715884105726".as_bytes(), 10)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 2);
|
||||||
|
|
||||||
|
let value = Value::Con(
|
||||||
|
Constant::Integer(
|
||||||
|
BigInt::parse_bytes("170141183460469231731687303715884105727".as_bytes(), 10)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 2);
|
||||||
|
|
||||||
|
let value = Value::Con(
|
||||||
|
Constant::Integer(
|
||||||
|
BigInt::parse_bytes("170141183460469231731687303715884105728".as_bytes(), 10)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 2);
|
||||||
|
|
||||||
|
let value = Value::Con(
|
||||||
|
Constant::Integer(
|
||||||
|
BigInt::parse_bytes("170141183460469231731687303715884105729".as_bytes(), 10)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 2);
|
||||||
|
|
||||||
|
let value = Value::Con(
|
||||||
|
Constant::Integer(
|
||||||
|
BigInt::parse_bytes("340282366920938463463374607431768211458".as_bytes(), 10)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 3);
|
||||||
|
|
||||||
|
let value = Value::Con(
|
||||||
|
Constant::Integer(
|
||||||
|
BigInt::parse_bytes("999999999999999999999999999999999999999999".as_bytes(), 10)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 3);
|
||||||
|
|
||||||
|
let value =
|
||||||
|
Value::Con(Constant::Integer(BigInt::parse_bytes("999999999999999999999999999999999999999999999999999999999999999999999999999999999999".as_bytes(), 10).unwrap()).into());
|
||||||
|
|
||||||
|
assert_eq!(value.to_ex_mem(), 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn integer_log2_oracle() {
|
||||||
|
// Values come from the Haskell implementation
|
||||||
|
assert_eq!(integer_log2(1.into()), 0);
|
||||||
|
assert_eq!(integer_log2(42.into()), 5);
|
||||||
|
assert_eq!(
|
||||||
|
integer_log2(BigInt::parse_bytes("18446744073709551615".as_bytes(), 10).unwrap()),
|
||||||
|
63
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
integer_log2(
|
||||||
|
BigInt::parse_bytes("999999999999999999999999999999".as_bytes(), 10).unwrap()
|
||||||
|
),
|
||||||
|
99
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
integer_log2(
|
||||||
|
BigInt::parse_bytes("170141183460469231731687303715884105726".as_bytes(), 10)
|
||||||
|
.unwrap()
|
||||||
|
),
|
||||||
|
126
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
integer_log2(
|
||||||
|
BigInt::parse_bytes("170141183460469231731687303715884105727".as_bytes(), 10)
|
||||||
|
.unwrap()
|
||||||
|
),
|
||||||
|
126
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
integer_log2(
|
||||||
|
BigInt::parse_bytes("170141183460469231731687303715884105728".as_bytes(), 10)
|
||||||
|
.unwrap()
|
||||||
|
),
|
||||||
|
127
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
integer_log2(
|
||||||
|
BigInt::parse_bytes("340282366920938463463374607431768211458".as_bytes(), 10)
|
||||||
|
.unwrap()
|
||||||
|
),
|
||||||
|
128
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
integer_log2(
|
||||||
|
BigInt::parse_bytes("999999999999999999999999999999999999999999".as_bytes(), 10)
|
||||||
|
.unwrap()
|
||||||
|
),
|
||||||
|
139
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
integer_log2(BigInt::parse_bytes("999999999999999999999999999999999999999999999999999999999999999999999999999999999999".as_bytes(), 10).unwrap()),
|
||||||
|
279
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
|
|
||||||
|
use num_bigint::BigInt;
|
||||||
|
|
||||||
use crate::ast::{NamedDeBruijn, Term, Type};
|
use crate::ast::{NamedDeBruijn, Term, Type};
|
||||||
|
|
||||||
use super::{ExBudget, Value};
|
use super::{ExBudget, Value};
|
||||||
|
@ -37,9 +39,9 @@ pub enum Error {
|
||||||
#[error("Decoding utf8")]
|
#[error("Decoding utf8")]
|
||||||
Utf8(#[from] FromUtf8Error),
|
Utf8(#[from] FromUtf8Error),
|
||||||
#[error("Out of Bounds\n\nindex: {}\nbytestring: {}\npossible: 0 - {}", .0, hex::encode(.1), .1.len() - 1)]
|
#[error("Out of Bounds\n\nindex: {}\nbytestring: {}\npossible: 0 - {}", .0, hex::encode(.1), .1.len() - 1)]
|
||||||
ByteStringOutOfBounds(i128, Vec<u8>),
|
ByteStringOutOfBounds(BigInt, Vec<u8>),
|
||||||
#[error("Divide By Zero\n\n{0} / {1}")]
|
#[error("Divide By Zero\n\n{0} / {1}")]
|
||||||
DivideByZero(i128, i128),
|
DivideByZero(BigInt, BigInt),
|
||||||
#[error("Ed25519S PublicKey should be 32 bytes but it was {0}")]
|
#[error("Ed25519S PublicKey should be 32 bytes but it was {0}")]
|
||||||
UnexpectedEd25519PublicKeyLength(usize),
|
UnexpectedEd25519PublicKeyLength(usize),
|
||||||
#[error("Ed25519S Signature should be 64 bytes but it was {0}")]
|
#[error("Ed25519S Signature should be 64 bytes but it was {0}")]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{ops::Deref, rc::Rc};
|
use std::{ops::Deref, rc::Rc};
|
||||||
|
|
||||||
use pallas_primitives::babbage::{BigInt, Constr, PlutusData};
|
use num_integer::Integer;
|
||||||
|
use pallas_primitives::babbage::{Constr, PlutusData};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Constant, Type},
|
ast::{Constant, Type},
|
||||||
|
@ -10,7 +11,7 @@ use crate::{
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
cost_model::{BuiltinCosts, ExBudget},
|
cost_model::{BuiltinCosts, ExBudget},
|
||||||
Error, Value,
|
from_pallas_bigint, to_pallas_bigint, Error, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
//#[derive(std::cmp::PartialEq)]
|
//#[derive(std::cmp::PartialEq)]
|
||||||
|
@ -330,10 +331,9 @@ impl DefaultFunction {
|
||||||
(Value::Con(integer1), Value::Con(integer2)) => {
|
(Value::Con(integer1), Value::Con(integer2)) => {
|
||||||
match (integer1.as_ref(), integer2.as_ref()) {
|
match (integer1.as_ref(), integer2.as_ref()) {
|
||||||
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
||||||
match arg1.checked_add(*arg2) {
|
let result = arg1 + arg2;
|
||||||
Some(res) => Ok(Value::Con(Constant::Integer(res).into()).into()),
|
|
||||||
None => Err(Error::OverflowError),
|
Ok(Value::Con(Constant::Integer(result).into()).into())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -344,10 +344,9 @@ impl DefaultFunction {
|
||||||
(Value::Con(integer1), Value::Con(integer2)) => {
|
(Value::Con(integer1), Value::Con(integer2)) => {
|
||||||
match (integer1.as_ref(), integer2.as_ref()) {
|
match (integer1.as_ref(), integer2.as_ref()) {
|
||||||
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
||||||
match arg1.checked_sub(*arg2) {
|
let result = arg1 - arg2;
|
||||||
Some(res) => Ok(Value::Con(Constant::Integer(res).into()).into()),
|
|
||||||
None => Err(Error::OverflowError),
|
Ok(Value::Con(Constant::Integer(result).into()).into())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -358,9 +357,25 @@ impl DefaultFunction {
|
||||||
(Value::Con(integer1), Value::Con(integer2)) => {
|
(Value::Con(integer1), Value::Con(integer2)) => {
|
||||||
match (integer1.as_ref(), integer2.as_ref()) {
|
match (integer1.as_ref(), integer2.as_ref()) {
|
||||||
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
||||||
match arg1.checked_mul(*arg2) {
|
let result = arg1 * arg2;
|
||||||
Some(res) => Ok(Value::Con(Constant::Integer(res).into()).into()),
|
|
||||||
None => Err(Error::OverflowError),
|
Ok(Value::Con(Constant::Integer(result).into()).into())
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
DefaultFunction::DivideInteger => match (args[0].as_ref(), args[1].as_ref()) {
|
||||||
|
(Value::Con(integer1), Value::Con(integer2)) => {
|
||||||
|
match (integer1.as_ref(), integer2.as_ref()) {
|
||||||
|
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
||||||
|
if *arg2 != 0.into() {
|
||||||
|
let (result, _) = arg1.div_mod_floor(arg2);
|
||||||
|
|
||||||
|
Ok(Value::Con(Constant::Integer(result).into()).into())
|
||||||
|
} else {
|
||||||
|
Err(Error::DivideByZero(arg1.clone(), arg2.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -368,38 +383,16 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
DefaultFunction::DivideInteger => {
|
|
||||||
match (args[0].as_ref(), args[1].as_ref()) {
|
|
||||||
(Value::Con(integer1), Value::Con(integer2)) => {
|
|
||||||
match (integer1.as_ref(), integer2.as_ref()) {
|
|
||||||
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
|
||||||
if *arg2 != 0 {
|
|
||||||
let ret = (*arg1 as f64) / (*arg2 as f64);
|
|
||||||
|
|
||||||
Ok(Value::Con(Constant::Integer(ret.floor() as i128).into())
|
|
||||||
.into())
|
|
||||||
} else {
|
|
||||||
Err(Error::DivideByZero(*arg1, *arg2))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::QuotientInteger => match (args[0].as_ref(), args[1].as_ref()) {
|
DefaultFunction::QuotientInteger => match (args[0].as_ref(), args[1].as_ref()) {
|
||||||
(Value::Con(integer1), Value::Con(integer2)) => {
|
(Value::Con(integer1), Value::Con(integer2)) => {
|
||||||
match (integer1.as_ref(), integer2.as_ref()) {
|
match (integer1.as_ref(), integer2.as_ref()) {
|
||||||
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
||||||
if *arg2 != 0 {
|
if *arg2 != 0.into() {
|
||||||
let ret = (*arg1 as f64) / (*arg2 as f64);
|
let (result, _) = arg1.div_rem(arg2);
|
||||||
|
|
||||||
let ret = if ret < 0. { ret.ceil() } else { ret.floor() };
|
Ok(Value::Con(Constant::Integer(result).into()).into())
|
||||||
|
|
||||||
Ok(Value::Con(Constant::Integer(ret as i128).into()).into())
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error::DivideByZero(*arg1, *arg2))
|
Err(Error::DivideByZero(arg1.clone(), arg2.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -411,12 +404,12 @@ impl DefaultFunction {
|
||||||
(Value::Con(integer1), Value::Con(integer2)) => {
|
(Value::Con(integer1), Value::Con(integer2)) => {
|
||||||
match (integer1.as_ref(), integer2.as_ref()) {
|
match (integer1.as_ref(), integer2.as_ref()) {
|
||||||
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
||||||
if *arg2 != 0 {
|
if *arg2 != 0.into() {
|
||||||
let ret = arg1 % arg2;
|
let (_, result) = arg1.div_rem(arg2);
|
||||||
|
|
||||||
Ok(Value::Con(Constant::Integer(ret).into()).into())
|
Ok(Value::Con(Constant::Integer(result).into()).into())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::DivideByZero(*arg1, *arg2))
|
Err(Error::DivideByZero(arg1.clone(), arg2.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -428,12 +421,12 @@ impl DefaultFunction {
|
||||||
(Value::Con(integer1), Value::Con(integer2)) => {
|
(Value::Con(integer1), Value::Con(integer2)) => {
|
||||||
match (integer1.as_ref(), integer2.as_ref()) {
|
match (integer1.as_ref(), integer2.as_ref()) {
|
||||||
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
(Constant::Integer(arg1), Constant::Integer(arg2)) => {
|
||||||
if *arg2 != 0 {
|
if *arg2 != 0.into() {
|
||||||
let ret = arg1 % arg2;
|
let (_, result) = arg1.div_mod_floor(arg2);
|
||||||
|
|
||||||
Ok(Value::Con(Constant::Integer(ret.abs()).into()).into())
|
Ok(Value::Con(Constant::Integer(result).into()).into())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::DivideByZero(*arg1, *arg2))
|
Err(Error::DivideByZero(arg1.clone(), arg2.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -493,7 +486,12 @@ impl DefaultFunction {
|
||||||
(Value::Con(integer), Value::Con(byte_string)) => {
|
(Value::Con(integer), Value::Con(byte_string)) => {
|
||||||
match (integer.as_ref(), byte_string.as_ref()) {
|
match (integer.as_ref(), byte_string.as_ref()) {
|
||||||
(Constant::Integer(arg1), Constant::ByteString(arg2)) => {
|
(Constant::Integer(arg1), Constant::ByteString(arg2)) => {
|
||||||
let mut ret = vec![(arg1 % 256) as u8];
|
let wrap = arg1.mod_floor(&256.into());
|
||||||
|
|
||||||
|
let byte: u8 = wrap.try_into().unwrap();
|
||||||
|
|
||||||
|
let mut ret = vec![byte];
|
||||||
|
|
||||||
ret.extend(arg2.clone());
|
ret.extend(arg2.clone());
|
||||||
|
|
||||||
Ok(Value::Con(Constant::ByteString(ret).into()).into())
|
Ok(Value::Con(Constant::ByteString(ret).into()).into())
|
||||||
|
@ -512,8 +510,16 @@ impl DefaultFunction {
|
||||||
Constant::Integer(arg2),
|
Constant::Integer(arg2),
|
||||||
Constant::ByteString(arg3),
|
Constant::ByteString(arg3),
|
||||||
) => {
|
) => {
|
||||||
let skip = if 0 > *arg1 { 0 } else { *arg1 as usize };
|
let skip: usize = if arg1.lt(&0.into()) {
|
||||||
let take = if 0 > *arg2 { 0 } else { *arg2 as usize };
|
0
|
||||||
|
} else {
|
||||||
|
arg1.try_into().unwrap()
|
||||||
|
};
|
||||||
|
let take: usize = if arg2.lt(&0.into()) {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
arg2.try_into().unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
let ret: Vec<u8> =
|
let ret: Vec<u8> =
|
||||||
arg3.iter().skip(skip).take(take).cloned().collect();
|
arg3.iter().skip(skip).take(take).cloned().collect();
|
||||||
|
@ -529,7 +535,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::LengthOfByteString => match args[0].as_ref() {
|
DefaultFunction::LengthOfByteString => match args[0].as_ref() {
|
||||||
Value::Con(byte_string) => match byte_string.as_ref() {
|
Value::Con(byte_string) => match byte_string.as_ref() {
|
||||||
Constant::ByteString(arg1) => {
|
Constant::ByteString(arg1) => {
|
||||||
Ok(Value::Con(Constant::Integer(arg1.len() as i128).into()).into())
|
Ok(Value::Con(Constant::Integer(arg1.len().into()).into()).into())
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
|
@ -539,14 +545,14 @@ impl DefaultFunction {
|
||||||
(Value::Con(byte_string), Value::Con(integer)) => {
|
(Value::Con(byte_string), Value::Con(integer)) => {
|
||||||
match (byte_string.as_ref(), integer.as_ref()) {
|
match (byte_string.as_ref(), integer.as_ref()) {
|
||||||
(Constant::ByteString(arg1), Constant::Integer(arg2)) => {
|
(Constant::ByteString(arg1), Constant::Integer(arg2)) => {
|
||||||
let index = *arg2 as usize;
|
let index: i128 = arg2.try_into().unwrap();
|
||||||
|
|
||||||
if 0 <= *arg2 && index < arg1.len() {
|
if 0 <= index && index < arg1.len() as i128 {
|
||||||
let ret = arg1[index] as i128;
|
let ret = arg1[index as usize];
|
||||||
|
|
||||||
Ok(Value::Con(Constant::Integer(ret).into()).into())
|
Ok(Value::Con(Constant::Integer(ret.into()).into()).into())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ByteStringOutOfBounds(*arg2, arg1.to_vec()))
|
Err(Error::ByteStringOutOfBounds(arg2.clone(), arg1.to_vec()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -879,10 +885,11 @@ impl DefaultFunction {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let i: u64 = i.try_into().unwrap();
|
||||||
|
|
||||||
let constr_data = PlutusData::Constr(Constr {
|
let constr_data = PlutusData::Constr(Constr {
|
||||||
tag: convert_constr_to_tag(*i as u64).unwrap_or(ANY_TAG),
|
tag: convert_constr_to_tag(i).unwrap_or(ANY_TAG),
|
||||||
any_constructor: convert_constr_to_tag(*i as u64)
|
any_constructor: convert_constr_to_tag(i).map_or(Some(i), |_| None),
|
||||||
.map_or(Some(*i as u64), |_| None),
|
|
||||||
fields: data_list,
|
fields: data_list,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -938,8 +945,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::IData => match args[0].as_ref() {
|
DefaultFunction::IData => match args[0].as_ref() {
|
||||||
Value::Con(integer) => match integer.as_ref() {
|
Value::Con(integer) => match integer.as_ref() {
|
||||||
Constant::Integer(i) => Ok(Value::Con(
|
Constant::Integer(i) => Ok(Value::Con(
|
||||||
Constant::Data(PlutusData::BigInt(BigInt::Int((*i).try_into().unwrap())))
|
Constant::Data(PlutusData::BigInt(to_pallas_bigint(i))).into(),
|
||||||
.into(),
|
|
||||||
)
|
)
|
||||||
.into()),
|
.into()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -966,7 +972,7 @@ impl DefaultFunction {
|
||||||
Constant::Integer(
|
Constant::Integer(
|
||||||
convert_tag_to_constr(c.tag)
|
convert_tag_to_constr(c.tag)
|
||||||
.unwrap_or_else(|| c.any_constructor.unwrap())
|
.unwrap_or_else(|| c.any_constructor.unwrap())
|
||||||
as i128,
|
.into(),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
Constant::ProtoList(
|
Constant::ProtoList(
|
||||||
|
@ -1048,13 +1054,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::UnIData => match args[0].as_ref() {
|
DefaultFunction::UnIData => match args[0].as_ref() {
|
||||||
Value::Con(data) => match data.as_ref() {
|
Value::Con(data) => match data.as_ref() {
|
||||||
Constant::Data(PlutusData::BigInt(b)) => {
|
Constant::Data(PlutusData::BigInt(b)) => {
|
||||||
if let BigInt::Int(i) = b {
|
Ok(Value::Con(Constant::Integer(from_pallas_bigint(b)).into()).into())
|
||||||
let x: i128 = (*i).try_into().unwrap();
|
|
||||||
|
|
||||||
Ok(Value::Con(Constant::Integer(x).into()).into())
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
v => Err(Error::DeserialisationError(
|
v => Err(Error::DeserialisationError(
|
||||||
"UnMapData".to_string(),
|
"UnMapData".to_string(),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{rc::Rc, str::FromStr};
|
use std::{ops::Neg, rc::Rc, str::FromStr};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Constant, Name, Program, Term, Type},
|
ast::{Constant, Name, Program, Term, Type},
|
||||||
|
@ -6,6 +6,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use interner::Interner;
|
use interner::Interner;
|
||||||
|
use num_bigint::BigInt;
|
||||||
use pallas_primitives::{alonzo::PlutusData, Fragment};
|
use pallas_primitives::{alonzo::PlutusData, Fragment};
|
||||||
use peg::{error::ParseError, str::LineCol};
|
use peg::{error::ParseError, str::LineCol};
|
||||||
|
|
||||||
|
@ -157,8 +158,8 @@ peg::parser! {
|
||||||
rule number() -> isize
|
rule number() -> isize
|
||||||
= n:$("-"* ['0'..='9']+) {? n.parse().or(Err("isize")) }
|
= n:$("-"* ['0'..='9']+) {? n.parse().or(Err("isize")) }
|
||||||
|
|
||||||
rule big_number() -> i128
|
rule big_number() -> BigInt
|
||||||
= n:$("-"* ['0'..='9']+) {? n.parse().or(Err("i128")) }
|
= n:$("-"* ['0'..='9']+) {? (if n.starts_with('-') { BigInt::parse_bytes(&n.as_bytes()[1..], 10).map(|i| i.neg()) } else { BigInt::parse_bytes(n.as_bytes(), 10) }).ok_or("BigInt") }
|
||||||
|
|
||||||
rule boolean() -> bool
|
rule boolean() -> bool
|
||||||
= b:$("True" / "False") { b == "True" }
|
= b:$("True" / "False") { b == "True" }
|
||||||
|
@ -257,6 +258,8 @@ peg::parser! {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use num_bigint::BigInt;
|
||||||
|
|
||||||
use crate::ast::{Constant, Name, Program, Term, Type, Unique};
|
use crate::ast::{Constant, Name, Program, Term, Type, Unique};
|
||||||
use crate::builtins::DefaultFunction;
|
use crate::builtins::DefaultFunction;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -277,7 +280,7 @@ mod test {
|
||||||
parameter_name: x.clone().into(),
|
parameter_name: x.clone().into(),
|
||||||
body: Rc::new(Term::Var(x.into())),
|
body: Rc::new(Term::Var(x.into())),
|
||||||
}),
|
}),
|
||||||
argument: Rc::new(Term::Constant(Constant::Integer(0).into()))
|
argument: Rc::new(Term::Constant(Constant::Integer(0.into()).into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -344,7 +347,7 @@ mod test {
|
||||||
super::program(uplc).unwrap(),
|
super::program(uplc).unwrap(),
|
||||||
Program::<Name> {
|
Program::<Name> {
|
||||||
version: (11, 22, 33),
|
version: (11, 22, 33),
|
||||||
term: Term::Constant(Constant::Integer(11).into()),
|
term: Term::Constant(Constant::Integer(11.into()).into()),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -492,7 +495,7 @@ mod test {
|
||||||
term: Term::Apply {
|
term: Term::Apply {
|
||||||
function: Rc::new(Term::Apply {
|
function: Rc::new(Term::Apply {
|
||||||
function: Rc::new(Term::Builtin(DefaultFunction::ConsByteString)),
|
function: Rc::new(Term::Builtin(DefaultFunction::ConsByteString)),
|
||||||
argument: Rc::new(Term::Constant(Constant::Integer(256).into())),
|
argument: Rc::new(Term::Constant(Constant::Integer(256.into()).into())),
|
||||||
}),
|
}),
|
||||||
argument: Rc::new(Term::Constant(Constant::ByteString(vec![]).into()))
|
argument: Rc::new(Term::Constant(Constant::ByteString(vec![]).into()))
|
||||||
}
|
}
|
||||||
|
@ -511,9 +514,9 @@ mod test {
|
||||||
function: Rc::new(Term::Apply {
|
function: Rc::new(Term::Apply {
|
||||||
function: Rc::new(Term::Apply {
|
function: Rc::new(Term::Apply {
|
||||||
function: Rc::new(Term::Builtin(DefaultFunction::SliceByteString)),
|
function: Rc::new(Term::Builtin(DefaultFunction::SliceByteString)),
|
||||||
argument: Rc::new(Term::Constant(Constant::Integer(1).into())),
|
argument: Rc::new(Term::Constant(Constant::Integer(1.into()).into())),
|
||||||
}),
|
}),
|
||||||
argument: Rc::new(Term::Constant(Constant::Integer(2).into())),
|
argument: Rc::new(Term::Constant(Constant::Integer(2.into()).into())),
|
||||||
}),
|
}),
|
||||||
argument: Rc::new(Term::Constant(
|
argument: Rc::new(Term::Constant(
|
||||||
Constant::ByteString(vec![0x00, 0xFF, 0xAA]).into()
|
Constant::ByteString(vec![0x00, 0xFF, 0xAA]).into()
|
||||||
|
@ -553,7 +556,10 @@ mod test {
|
||||||
argument: Rc::new(Term::Constant(Constant::ByteString(vec![0x00]).into()))
|
argument: Rc::new(Term::Constant(Constant::ByteString(vec![0x00]).into()))
|
||||||
}),
|
}),
|
||||||
argument: Rc::new(Term::Constant(
|
argument: Rc::new(Term::Constant(
|
||||||
Constant::Integer(9223372036854775808).into()
|
Constant::Integer(
|
||||||
|
BigInt::parse_bytes("9223372036854775808".as_bytes(), 10).unwrap()
|
||||||
|
)
|
||||||
|
.into()
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -704,9 +710,12 @@ mod test {
|
||||||
vec![
|
vec![
|
||||||
Constant::ProtoList(
|
Constant::ProtoList(
|
||||||
Type::Integer,
|
Type::Integer,
|
||||||
vec![Constant::Integer(14), Constant::Integer(42)]
|
vec![Constant::Integer(14.into()), Constant::Integer(42.into())]
|
||||||
),
|
),
|
||||||
Constant::ProtoList(Type::Integer, vec![Constant::Integer(1337)])
|
Constant::ProtoList(
|
||||||
|
Type::Integer,
|
||||||
|
vec![Constant::Integer(1337.into())]
|
||||||
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
|
@ -733,7 +742,7 @@ mod test {
|
||||||
term: Term::Constant(
|
term: Term::Constant(
|
||||||
Constant::ProtoList(
|
Constant::ProtoList(
|
||||||
Type::Integer,
|
Type::Integer,
|
||||||
vec![Constant::Integer(14), Constant::Integer(42)],
|
vec![Constant::Integer(14.into()), Constant::Integer(42.into())],
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
)
|
)
|
||||||
|
@ -776,7 +785,7 @@ mod test {
|
||||||
Constant::ProtoPair(
|
Constant::ProtoPair(
|
||||||
Type::Integer,
|
Type::Integer,
|
||||||
Type::ByteString,
|
Type::ByteString,
|
||||||
Constant::Integer(14).into(),
|
Constant::Integer(14.into()).into(),
|
||||||
Constant::ByteString(vec![0x42]).into(),
|
Constant::ByteString(vec![0x42]).into(),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
|
@ -801,7 +810,7 @@ mod test {
|
||||||
Constant::String(String::from("foo")).into(),
|
Constant::String(String::from("foo")).into(),
|
||||||
Constant::ProtoList(
|
Constant::ProtoList(
|
||||||
Type::Integer,
|
Type::Integer,
|
||||||
vec![Constant::Integer(14), Constant::Integer(42)],
|
vec![Constant::Integer(14.into()), Constant::Integer(42.into())],
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
)
|
)
|
||||||
|
@ -828,8 +837,8 @@ mod test {
|
||||||
Constant::ProtoPair(
|
Constant::ProtoPair(
|
||||||
Type::Integer,
|
Type::Integer,
|
||||||
Type::Integer,
|
Type::Integer,
|
||||||
Constant::Integer(14).into(),
|
Constant::Integer(14.into()).into(),
|
||||||
Constant::Integer(42).into()
|
Constant::Integer(42.into()).into()
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
)
|
)
|
||||||
|
@ -859,9 +868,9 @@ mod test {
|
||||||
term: Term::Apply {
|
term: Term::Apply {
|
||||||
function: Rc::new(Term::Apply {
|
function: Rc::new(Term::Apply {
|
||||||
function: Rc::new(Term::Builtin(default_function)),
|
function: Rc::new(Term::Builtin(default_function)),
|
||||||
argument: Rc::new(Term::Constant(Constant::Integer(x).into())),
|
argument: Rc::new(Term::Constant(Constant::Integer(x.into()).into())),
|
||||||
}),
|
}),
|
||||||
argument: Rc::new(Term::Constant(Constant::Integer(y).into()))
|
argument: Rc::new(Term::Constant(Constant::Integer(y.into()).into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::program_builder::WithTerm;
|
||||||
|
|
||||||
pub trait WithConstant: WithTerm {
|
pub trait WithConstant: WithTerm {
|
||||||
fn with_int(self, int: i128) -> Self::Next {
|
fn with_int(self, int: i128) -> Self::Next {
|
||||||
let term = Term::Constant(Constant::Integer(int).into());
|
let term = Term::Constant(Constant::Integer(int.into()).into());
|
||||||
self.next(term)
|
self.next(term)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue