Skip to content

Commit

Permalink
Fix TUPLE! crash after payload switch, round money
Browse files Browse the repository at this point in the history
This addresses two test failures that had crept in after the payload
fix that were low on the priority list (MONEY! and TUPLE!).

Tuples can now be a maximum size of 7 elements instead of 10.  Hardcoded
numbers of "10" had to be adjusted.

Rounding money did some interpretation of the ROUND/TO amount, so that
the type of the /TO argument would influence the type of the result.
So rounding $10.51 to 0.1 would give you 10.5, for instance.  Not clear
quite how the code was supposed to work before, but this makes it
seem to work and is clearer.
  • Loading branch information
hostilefork committed Jul 3, 2016
1 parent 82de750 commit 2c7d58f
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 24 deletions.
7 changes: 6 additions & 1 deletion src/core/n-strings.c
Expand Up @@ -801,8 +801,13 @@ REBNATIVE(to_hex)
}
else if (IS_TUPLE(arg)) {
REBINT n;
if (len < 0 || len > 2 * MAX_TUPLE || len > 2 * VAL_TUPLE_LEN(arg))
if (
len < 0
|| len > 2 * cast(REBINT, MAX_TUPLE)
|| len > 2 * VAL_TUPLE_LEN(arg)
){
len = 2 * VAL_TUPLE_LEN(arg);
}
for (n = 0; n < VAL_TUPLE_LEN(arg); n++)
buf = Form_Hex2(buf, VAL_TUPLE(arg)[n]);
for (; n < 3; n++)
Expand Down
40 changes: 26 additions & 14 deletions src/core/t-money.c
Expand Up @@ -213,35 +213,47 @@ REBTYPE(Money)
*D_OUT = *D_ARG(1);
return R_OUT;

case SYM_ROUND:
arg = D_ARG(3);
if (D_REF(2)) {
if (IS_INTEGER(arg))
SET_MONEY(arg, int_to_deci(VAL_INT64(arg)));
else if (IS_DECIMAL(arg) || IS_PERCENT(arg))
SET_MONEY(arg, decimal_to_deci(VAL_DECIMAL(arg)));
else if (!IS_MONEY(arg)) fail (Error_Invalid_Arg(arg));
case SYM_ROUND: {
REFINE(2, to);
PARAM(3, scale);

REBVAL *scale = ARG(scale);

REBVAL temp;
if (REF(to)) {
if (IS_INTEGER(scale))
SET_MONEY(&temp, int_to_deci(VAL_INT64(scale)));
else if (IS_DECIMAL(scale) || IS_PERCENT(scale))
SET_MONEY(&temp, decimal_to_deci(VAL_DECIMAL(scale)));
else if (IS_MONEY(scale))
temp = *scale;
else
fail (Error_Invalid_Arg(scale));
}
else
SET_MONEY(&temp, int_to_deci(0));

SET_MONEY(D_OUT, Round_Deci(
VAL_MONEY_AMOUNT(val),
Get_Round_Flags(frame_),
VAL_MONEY_AMOUNT(arg)
VAL_MONEY_AMOUNT(&temp)
));
if (D_REF(2)) {
if (IS_DECIMAL(arg) || IS_PERCENT(arg)) {

if (REF(to)) {
if (IS_DECIMAL(scale) || IS_PERCENT(scale)) {
REBDEC dec = deci_to_decimal(VAL_MONEY_AMOUNT(D_OUT));
VAL_RESET_HEADER(D_OUT, VAL_TYPE(arg));
VAL_RESET_HEADER(D_OUT, VAL_TYPE(scale));
VAL_DECIMAL(D_OUT) = dec;
return R_OUT;
}
if (IS_INTEGER(arg)) {
if (IS_INTEGER(scale)) {
REBI64 i64 = deci_to_int(VAL_MONEY_AMOUNT(D_OUT));
VAL_RESET_HEADER(D_OUT, REB_INTEGER);
VAL_INT64(D_OUT) = i64;
return R_OUT;
}
}
break;
break; }

case SYM_EVEN_Q:
case SYM_ODD_Q: {
Expand Down
4 changes: 2 additions & 2 deletions src/core/t-tuple.c
Expand Up @@ -83,7 +83,7 @@ void MAKE_Tuple(REBVAL *out, enum Reb_Kind type, const REBVAL *arg)
RELVAL *item = VAL_ARRAY_AT(arg);

for (; NOT_END(item); ++item, ++vp, ++len) {
if (len >= 10) goto bad_make;
if (len >= MAX_TUPLE) goto bad_make;
if (IS_INTEGER(item)) {
n = Int32(item);
}
Expand All @@ -99,7 +99,7 @@ void MAKE_Tuple(REBVAL *out, enum Reb_Kind type, const REBVAL *arg)

VAL_TUPLE_LEN(out) = len;

for (; len < 10; len++) *vp++ = 0;
for (; len < MAX_TUPLE; len++) *vp++ = 0;
return;
}

Expand Down
5 changes: 3 additions & 2 deletions src/include/sys-value.h
Expand Up @@ -1035,7 +1035,7 @@ inline static void SET_TIME(RELVAL *v, REBI64 nanoseconds) {
//
//=////////////////////////////////////////////////////////////////////////=//
//
// TUPLE! is a Rebol2/R3-Alpha concept to fit up to 10 byte-sized integers
// TUPLE! is a Rebol2/R3-Alpha concept to fit up to 7 byte-sized integers
// directly into a value payload without needing to make a series allocation.
// At source level they would be numbers separated by dots, like `1.2.3.4.5`.
// This was mainly applied for IP addresses and RGB/RGBA constants, and
Expand All @@ -1048,7 +1048,8 @@ inline static void SET_TIME(RELVAL *v, REBI64 nanoseconds) {
// generalized partner to PATH!, where `a.b.1` would be like a/b/1
//

#define MAX_TUPLE 10
#define MAX_TUPLE \
((sizeof(REBCNT) * 2) - 1) // for same properties on 64-bit and 32-bit

#define VAL_TUPLE(v) \
((v)->payload.tuple.tuple + 1)
Expand Down
8 changes: 3 additions & 5 deletions tests/core-tests.r
Expand Up @@ -2415,7 +2415,7 @@
; minimum
[tuple? make tuple! []]
; maximum
[tuple? 255.255.255.255.255.255.255.255.255.255]
[tuple? 255.255.255.255.255.255.255]
[error? try [load "255.255.255.255.255.255.255.255.255.255.255"]]
; datatypes/typeset.r
[typeset? any-array!]
Expand Down Expand Up @@ -2980,11 +2980,9 @@
[equal? 0.0.0 0.0.0]
[not equal? 0.0.1 0.0.0]
; tuple! right-pads with 0
[equal? 1.0.0 1.0.0.0.0.0.0.0.0.0]
[equal? 1.0.0 1.0.0.0.0.0.0]
; tuple! right-pads with 0
[equal? 1.0.0.0.0.0.0.0.0.0 1.0.0]
; tuple! right-pads with 0
[not equal? 1.0.0 0.0.0.0.0.0.0.1.0.0]
[equal? 1.0.0.0.0.0.0 1.0.0]
; No implicit to binary! from tuple!
[
a-value: 0.0.0.0
Expand Down

0 comments on commit 2c7d58f

Please sign in to comment.