-
Notifications
You must be signed in to change notification settings - Fork 37
Implement system macro make_decimal #986
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/lazy/expanded/macro_evaluator.rs
Outdated
|
||
/// Given a [`ValueExpr`], this function will expand it into its underlying value; An | ||
/// error is return if the value does not expand to exactly one Int. | ||
fn get_integer(&self, env: Environment<'top, D>, value: ValueExpr<'top, D>) -> IonResult<Int> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The need for this type of function has popped up a couple times now. Thinking about pulling it out into a standalone function, or something similarly reusable.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #986 +/- ##
=======================================
Coverage 78.46% 78.47%
=======================================
Files 138 138
Lines 33290 33385 +95
Branches 33290 33385 +95
=======================================
+ Hits 26121 26198 +77
- Misses 5177 5179 +2
- Partials 1992 2008 +16 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
New rust just dropped today.. clippy lints are going wild with the enabling of uninlined format args. |
Will follow up with a PR for the clippy warnings. It's a bit much to include here, especially since they all seem unrelated to this PR. |
src/lazy/expanded/macro_evaluator.rs
Outdated
let expo_expr = self.arguments.next().ok_or(IonError::decoding_error("`make_decimal` takes 2 integer arguments; missing second argument"))?; | ||
let exponent = self.get_integer(environment, expo_expr?)?; | ||
|
||
let decimal = Decimal::new(coefficient, exponent.as_i64().ok_or_else(|| IonError::decoding_error("Unable to convert coefficient Int to i64"))?); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth updating this error message to say something like "coefficient is out of the range supported by this implementation" so that it's clear that this is an intentional limitation in the library.
src/lazy/expanded/macro_evaluator.rs
Outdated
) -> IonResult<MacroExpansionStep<'top, D>> { | ||
// Arguments should be: (coefficient exponent) | ||
// Both coefficient and exponent should evaluate to a single integer value. | ||
let coeff_expr = self.arguments.next().ok_or(IonError::decoding_error("`make_decimal` takes 2 integer arguments"))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small change to be explicit about the problem that was encountered.
let coeff_expr = self.arguments.next().ok_or(IonError::decoding_error("`make_decimal` takes 2 integer arguments"))?; | |
let coeff_expr = self.arguments.next().ok_or(IonError::decoding_error("`make_decimal` takes 2 integer arguments; found 0 arguments"))?; |
src/lazy/expanded/macro_evaluator.rs
Outdated
let coeff_expr = self.arguments.next().ok_or(IonError::decoding_error("`make_decimal` takes 2 integer arguments"))?; | ||
let coefficient = self.get_integer(environment, coeff_expr?)?; | ||
|
||
let expo_expr = self.arguments.next().ok_or(IonError::decoding_error("`make_decimal` takes 2 integer arguments; missing second argument"))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(very optional) Minor suggestion to make the message consistent with my suggested change for the previous error message.
let expo_expr = self.arguments.next().ok_or(IonError::decoding_error("`make_decimal` takes 2 integer arguments; missing second argument"))?; | |
let expo_expr = self.arguments.next().ok_or(IonError::decoding_error("`make_decimal` takes 2 integer arguments; found only 1 argument"))?; |
src/lazy/expanded/macro_evaluator.rs
Outdated
let mut evaluator = MacroEvaluator::new_with_environment(env); | ||
evaluator.push(invocation.expand()?); | ||
let int_arg = match evaluator.next()? { | ||
None => IonResult::decoding_error("`make_decimal` takes two integers as arguments; empty value found"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be a slight improvement to indicate which parameter was problematic, and it also prepares this for being generalized as a stand-alone helper function.
format!("`make_decimal` parameter {i} must be an integer, but argument was absent")
(And similarly for the "multiple values" case.)
@@ -3134,6 +3202,72 @@ mod tests { | |||
) | |||
} | |||
|
|||
#[test] | |||
fn make_decimal_eexp() -> IonResult<()> { | |||
stream_eq( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor suggestion—make each expression in the test input produce a different value so that it's obvious where something may have gone wrong.
} | ||
|
||
#[test] | ||
fn make_decimal_arg_errors() -> IonResult<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to test for a case like (:make_decimal 1 2 3)
, or is checking the number of arguments handled elsewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number of provided arguments is checked in the text parser itself, yea. I need to look though to see if the same is happening in the binary reader.
|
||
// A simple wrapper for make_decimal's known arguments. Provides context for error reporting, and | ||
// functionality to expand e-exp and validate integer types. | ||
struct MakeDecimalArgument<'top, D: Decoder>(&'static str, ValueExpr<'top, D>); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making this a little closer to reusable. I'll probably make it general use with the make_timestamp
implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will you call it then? NamedIntegerArgument
or something maybe? You'd have to add another field to name the context (macro) in the error messaging, and at that point you might as well name the fields 🤔...
|
||
// A simple wrapper for make_decimal's known arguments. Provides context for error reporting, and | ||
// functionality to expand e-exp and validate integer types. | ||
struct MakeDecimalArgument<'top, D: Decoder>(&'static str, ValueExpr<'top, D>); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will you call it then? NamedIntegerArgument
or something maybe? You'd have to add another field to name the context (macro) in the error messaging, and at that point you might as well name the fields 🤔...
Issue #, if available: #942
Description of changes:
This PR implements the
make_decimal
system macro.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.