Skip to content

Commit

Permalink
Merge pull request #1586 from radixdlt/test/dec_pdec_macro_tests
Browse files Browse the repository at this point in the history
Fix `dec!()`/`pdec!()` macros and more tests
  • Loading branch information
iamyulong authored Sep 22, 2023
2 parents d846ed4 + 2988094 commit 9b4b2ad
Show file tree
Hide file tree
Showing 83 changed files with 600 additions and 18 deletions.
63 changes: 48 additions & 15 deletions radix-engine-macros/src/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,39 @@ extern crate radix_engine_common;
macro_rules! get_decimal {
($type:ident) => {
paste! {
fn [< get_ $type:snake:lower _from_expr >](expr: &Expr) -> Result<$type> {
fn [< get_ $type:snake:lower _from_expr >](expr: &Expr, negate: bool) -> Result<$type> {
match expr {
Expr::Lit(lit) => match &lit.lit {
Lit::Str(lit_str) => $type::try_from(lit_str.value())
.map_err(|err| Error::new(lit_str.span(), [< $type:snake:lower _error_reason >](err).to_string())),
Lit::Str(lit_str) => {
// Do not allow string literal preceeded with '-', eg. -"12.3"
if !negate {
$type::try_from(lit_str.value())
.map_err(|err| Error::new(lit_str.span(), [< $type:snake:lower _error_reason >](err).to_string()))
}
else {
Err(Error::new(
lit_str.span(),
"This macro only supports string, integer and float literals.",
))
}
},
Lit::Int(lit_int) => {
if lit_int.suffix() != "" {
Err(Error::new(
lit_int.span(),
format!("No suffix is allowed. Remove the {}.", lit_int.suffix()),
))
} else {
$type::try_from(lit_int.base10_digits())
.map_err(|err| Error::new(lit_int.span(), [< $type:snake:lower _error_reason >](err).to_string()))
let mut val = $type::try_from(lit_int.base10_digits())
.map_err(|err| Error::new(lit_int.span(), [< $type:snake:lower _error_reason >](err).to_string()))?;

// Negate received value if negate flag is set.
// Safe from overflow.
if negate {
val = val.checked_neg()
.ok_or(Error::new(lit_int.span(), [< $type:snake:lower _error_reason >]([< Parse $type Error >]::Overflow).to_string()))?;
}
Ok(val)
}
}
Lit::Float(lit_float) => {
Expand All @@ -32,7 +51,19 @@ macro_rules! get_decimal {
format!("No suffix is allowed. Remove the {}.", lit_float.suffix()),
))
} else {
$type::try_from(lit_float.base10_digits())
let digits = lit_float.base10_digits();

// Preceed the literal digits with '-" if negate flag is set.
// And then convert received string to decimal.
// This is to avoid negation of the received decimal, which
// overflows for MIN value.
let s = if negate {
"-".to_string() + digits
} else {
digits.to_string()
};

$type::try_from(s)
.map_err(|err| Error::new(lit_float.span(), [< $type:snake:lower _error_reason >](err).to_string()))
}
}
Expand All @@ -43,13 +74,15 @@ macro_rules! get_decimal {
},
Expr::Unary(unary) => match unary.op {
UnOp::Neg(unary_neg) => {
let res = [< get_ $type:snake:lower _from_expr >](unary.expr.as_ref());
match res {
Ok(val) => {
let val = val.checked_neg().ok_or(Error::new(unary_neg.span, "Parsing failed due to overflow."))?;
Ok(val)
},
Err(err) => Err(Error::new(unary_neg.span, err)),
// Do not allow multiple '-'
if !negate {
[< get_ $type:snake:lower _from_expr >](unary.expr.as_ref(), true)
}
else {
Err(Error::new(
unary_neg.span(),
"This macro only supports string, integer and float literals.",
))
}
}
other_unary => Err(Error::new(
Expand Down Expand Up @@ -121,7 +154,7 @@ pub fn to_decimal(input: TokenStream) -> Result<TokenStream> {
// Parse the input into an Expression
let expr = parse::<Expr>(input)?;

let decimal = get_decimal_from_expr(&expr)?;
let decimal = get_decimal_from_expr(&expr, false)?;
let int = decimal.0;
let arr = int.to_digits();
let i0 = arr[0];
Expand All @@ -137,7 +170,7 @@ pub fn to_precise_decimal(input: TokenStream) -> Result<TokenStream> {
// Parse the input into an Expression
let expr = parse::<Expr>(input)?;

let decimal = get_precise_decimal_from_expr(&expr)?;
let decimal = get_precise_decimal_from_expr(&expr, false)?;
let int = decimal.0;
let arr = int.to_digits();
let i0 = arr[0];
Expand Down
1 change: 1 addition & 0 deletions radix-engine-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ paste = { version = "1.0.13" }
lazy_static = { version = "1.4.0" }
hex = { version = "0.4.3", default-features = false }
tuple-return = { path = "./tests/blueprints/tuple-return", features = ["test"], default-features = false }
trybuild = { version = "1.0.85" }

[build-dependencies]
walkdir = { version = "2.3.3", optional = true }
Expand Down
3 changes: 2 additions & 1 deletion radix-engine-tests/tests/blueprints/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ members = [
"wasm_non_mvp",
"royalty-edge-cases",
"system_wasm_buffers",
"event-replacement"
"event-replacement",
"decimal"
]

[profile.release]
Expand Down
15 changes: 15 additions & 0 deletions radix-engine-tests/tests/blueprints/decimal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "decimal"
version = "1.0.0-rc1"
edition = "2021"

[dependencies]
sbor = { path = "../../../../sbor" }
scrypto = { path = "../../../../scrypto" }

[dev-dependencies]
radix-engine = { path = "../../../../radix-engine" }

[lib]
doctest = false
crate-type = ["cdylib", "lib"]
35 changes: 35 additions & 0 deletions radix-engine-tests/tests/blueprints/decimal/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use scrypto::prelude::*;

#[blueprint]
mod cast_test {
const GD: Decimal = dec!(2);
const GP: PreciseDecimal = pdec!(2);

struct DecimalTest {}

impl DecimalTest {
pub fn test_dec_macro() -> Decimal {
const C: Decimal = dec!("1111.2222");
static S: Decimal = dec!(2222.1111);

C.checked_add(S)
.unwrap()
.checked_add(dec!(-0.3333))
.unwrap()
.checked_mul(GD)
.unwrap()
}

pub fn test_pdec_macro() -> PreciseDecimal {
const C: PreciseDecimal = pdec!("1111.2222");
static S: PreciseDecimal = pdec!(2222.1111);

C.checked_add(S)
.unwrap()
.checked_add(pdec!(-0.3333))
.unwrap()
.checked_mul(GP)
.unwrap()
}
}
}
31 changes: 31 additions & 0 deletions radix-engine-tests/tests/dec_macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[workspace]
members = ["."]

[package]
name = "dec_macros"
version = "1.0.0-rc1"
edition = "2021"

[dependencies]
radix-engine-interface = { path = "../../../radix-engine-interface", default-features = false }

# Stub lib to make 'trybuild' crate happy
[lib]
path = "src/lib.rs"

# Below targets are not required to for the 'dec_macro' tests.
# Adding just a few as a template.
# If one needs to build some other target with 'cargo build' then below shall be updated.
[[bin]]
name = "dec_success"
path = "src/dec_success.rs"

[[bin]]
name = "dec_err_expr_not_supported"
path = "src/dec_err_expr_not_supported.rs"

[features]
default = ["std"]
std = ["radix-engine-interface/std"]
alloc = ["radix-engine-interface/alloc"]

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(1.);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: If there is a decimal point, the number must include at least one digit after it.
--> src/dec_err_empty_fractional_part_1.rs:4:29
|
4 | const X: Decimal = dec!(1.);
| ^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!("1.");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: If there is a decimal point, the number must include at least one digit after it.
--> src/dec_err_empty_fractional_part_2.rs:4:29
|
4 | const X: Decimal = dec!("1.");
| ^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(".0");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: If there is a decimal point, the number must include at least one digit before it. Use a 0 if necessary.
--> src/dec_err_empty_integral_part.rs:4:29
|
4 | const X: Decimal = dec!(".0");
| ^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(.1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: expected expression
--> src/dec_err_expected_expr.rs:4:29
|
4 | const X: Decimal = dec!(.1);
| ^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(a);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: This macro only supports string, integer and float literals.
--> src/dec_err_expr_not_supported.rs:4:29
|
4 | const X: Decimal = dec!(a);
| ^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(!1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: This macro only supports string, integer and float literals.
--> src/dec_err_expr_unary_op_not_supported.rs:4:29
|
4 | const X: Decimal = dec!(!1);
| ^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(11.12f64);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: No suffix is allowed. Remove the f64.
--> src/dec_err_float_suffix.rs:4:29
|
4 | const X: Decimal = dec!(11.12f64);
| ^^^^^^^^
5 changes: 5 additions & 0 deletions radix-engine-tests/tests/dec_macros/src/dec_err_int_suffix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(11_i64);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: No suffix is allowed. Remove the i64.
--> src/dec_err_int_suffix.rs:4:29
|
4 | const X: Decimal = dec!(11_i64);
| ^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(11.12e3);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: There is an invalid character.
--> src/dec_err_invalid_digit.rs:4:29
|
4 | const X: Decimal = dec!(11.12e3);
| ^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!('a');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: This macro only supports string, integer and float literals.
--> src/dec_err_literal_not_supported.rs:4:29
|
4 | const X: Decimal = dec!('a');
| ^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!("1.000.0");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: A decimal cannot have more than one decimal point.
--> src/dec_err_more_than_one_decimal_point.rs:4:29
|
4 | const X: Decimal = dec!("1.000.0");
| ^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(--1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: This macro only supports string, integer and float literals.
--> src/dec_err_multiple_negations.rs:4:30
|
4 | const X: Decimal = dec!(--1);
| ^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(-"112.3");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: This macro only supports string, integer and float literals.
--> src/dec_err_negation_and_string.rs:4:30
|
4 | const X: Decimal = dec!(-"112.3");
| ^^^^^^^
5 changes: 5 additions & 0 deletions radix-engine-tests/tests/dec_macros/src/dec_err_overflow_1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(-3138550867693340381917894711603833208051.177722232017256449);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: The number is too large to fit in a decimal.
--> src/dec_err_overflow_1.rs:4:30
|
4 | const X: Decimal = dec!(-3138550867693340381917894711603833208051.177722232017256449);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 changes: 5 additions & 0 deletions radix-engine-tests/tests/dec_macros/src/dec_err_overflow_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!("-3138550867693340381917894711603833208051.177722232017256449");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: The number is too large to fit in a decimal.
--> src/dec_err_overflow_2.rs:4:29
|
4 | const X: Decimal = dec!("-3138550867693340381917894711603833208051.177722232017256449");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 changes: 5 additions & 0 deletions radix-engine-tests/tests/dec_macros/src/dec_err_overflow_3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use radix_engine_interface::prelude::*;

fn main() {
const X: Decimal = dec!(3138550867693340381917894711603833208051.177722232017256448);
}
Loading

0 comments on commit 9b4b2ad

Please sign in to comment.