Implement unary operators: bitwise not, pre/post increment/decrement (#4116)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -373,6 +373,138 @@ ecma_big_uint_to_string (ecma_extended_primitive_t *value_p, /**< BigUInt value
|
||||
return result_p;
|
||||
} /* ecma_big_uint_to_string */
|
||||
|
||||
/**
|
||||
* Increase the value of a BigUInt value by 1
|
||||
*
|
||||
* return new BigInt value, NULL on error
|
||||
*/
|
||||
ecma_extended_primitive_t *
|
||||
ecma_big_uint_increase (ecma_extended_primitive_t *value_p) /**< BigUInt value */
|
||||
{
|
||||
uint32_t size = ECMA_BIGINT_GET_SIZE (value_p);
|
||||
|
||||
JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0);
|
||||
|
||||
ecma_bigint_digit_t *digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
|
||||
ecma_bigint_digit_t *digits_end_p = ECMA_BIGINT_GET_DIGITS (value_p, size);
|
||||
|
||||
if (JERRY_UNLIKELY (digits_p[0] == ~((ecma_bigint_digit_t) 0) && digits_end_p[-1] == ~((ecma_bigint_digit_t) 0)))
|
||||
{
|
||||
do
|
||||
{
|
||||
digits_p++;
|
||||
}
|
||||
while (digits_p < digits_end_p && digits_p[0] == ~((ecma_bigint_digit_t) 0));
|
||||
|
||||
if (digits_p == digits_end_p)
|
||||
{
|
||||
ecma_extended_primitive_t *result_value_p;
|
||||
result_value_p = ecma_bigint_create ((uint32_t) (size + sizeof (ecma_bigint_digit_t)));
|
||||
|
||||
if (JERRY_UNLIKELY (result_value_p == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), 0, size);
|
||||
*ECMA_BIGINT_GET_DIGITS (result_value_p, size) = 1;
|
||||
return result_value_p;
|
||||
}
|
||||
|
||||
digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size);
|
||||
|
||||
if (JERRY_UNLIKELY (result_value_p == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0);
|
||||
|
||||
while (digits_p[0] == ~((ecma_bigint_digit_t) 0))
|
||||
{
|
||||
digits_p++;
|
||||
*result_p++ = 0;
|
||||
}
|
||||
|
||||
*result_p++ = (*digits_p++) + 1;
|
||||
|
||||
if (digits_p < digits_end_p)
|
||||
{
|
||||
memcpy (result_p, digits_p, (size_t) ((uint8_t *) digits_end_p - (uint8_t *) digits_p));
|
||||
}
|
||||
return result_value_p;
|
||||
} /* ecma_big_uint_increase */
|
||||
|
||||
/**
|
||||
* Decrease the value of a BigUInt value by 1
|
||||
*
|
||||
* return new BigInt value, NULL on error
|
||||
*/
|
||||
ecma_extended_primitive_t *
|
||||
ecma_big_uint_decrease (ecma_extended_primitive_t *value_p) /**< BigUInt value */
|
||||
{
|
||||
uint32_t size = ECMA_BIGINT_GET_SIZE (value_p);
|
||||
|
||||
JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0);
|
||||
|
||||
ecma_bigint_digit_t *digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
|
||||
ecma_bigint_digit_t *digits_end_p = ECMA_BIGINT_GET_DIGITS (value_p, size);
|
||||
|
||||
JERRY_ASSERT (size > sizeof (ecma_bigint_digit_t) || *digits_p > 1);
|
||||
|
||||
if (JERRY_UNLIKELY (digits_p[0] == 0 && digits_end_p[-1] == 1))
|
||||
{
|
||||
do
|
||||
{
|
||||
digits_p++;
|
||||
JERRY_ASSERT (digits_p < digits_end_p);
|
||||
}
|
||||
while (digits_p[0] == 0);
|
||||
|
||||
if (digits_p + 1 == digits_end_p)
|
||||
{
|
||||
size -= (uint32_t) sizeof (ecma_bigint_digit_t);
|
||||
ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size);
|
||||
|
||||
if (JERRY_UNLIKELY (result_value_p == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), 0xff, size);
|
||||
return result_value_p;
|
||||
}
|
||||
|
||||
digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size);
|
||||
|
||||
if (JERRY_UNLIKELY (result_value_p == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0);
|
||||
|
||||
while (digits_p[0] == 0)
|
||||
{
|
||||
digits_p++;
|
||||
*result_p++ = ~((ecma_bigint_digit_t) 0);
|
||||
}
|
||||
|
||||
*result_p++ = (*digits_p++) - 1;
|
||||
|
||||
if (digits_p < digits_end_p)
|
||||
{
|
||||
memcpy (result_p, digits_p, (size_t) ((uint8_t *) digits_end_p - (uint8_t *) digits_p));
|
||||
}
|
||||
return result_value_p;
|
||||
} /* ecma_big_uint_decrease */
|
||||
|
||||
/**
|
||||
* Add right BigUInt value to the left BigUInt value
|
||||
*
|
||||
|
||||
@@ -103,6 +103,9 @@ ecma_extended_primitive_t *ecma_big_uint_mul_digit (ecma_extended_primitive_t *v
|
||||
uint8_t *ecma_big_uint_to_string (ecma_extended_primitive_t *value_p, uint32_t radix,
|
||||
uint32_t *char_start_p, uint32_t *char_size_p);
|
||||
|
||||
ecma_extended_primitive_t *ecma_big_uint_increase (ecma_extended_primitive_t *value_p);
|
||||
ecma_extended_primitive_t *ecma_big_uint_decrease (ecma_extended_primitive_t *value_p);
|
||||
|
||||
ecma_extended_primitive_t *ecma_big_uint_add (ecma_extended_primitive_t *left_value_p,
|
||||
ecma_extended_primitive_t *right_value_p);
|
||||
ecma_extended_primitive_t *ecma_big_uint_sub (ecma_extended_primitive_t *left_value_p,
|
||||
|
||||
@@ -34,6 +34,34 @@ ecma_bigint_raise_memory_error (void)
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Cannot allocate memory for a BigInt value"));
|
||||
} /* ecma_bigint_raise_memory_error */
|
||||
|
||||
/**
|
||||
* Create a single digit long BigInt value
|
||||
*
|
||||
* @return ecma BigInt value or ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_bigint_create_from_digit (ecma_bigint_digit_t digit, /* single digit */
|
||||
bool sign) /* set ECMA_BIGINT_SIGN if true */
|
||||
{
|
||||
JERRY_ASSERT (digit != 0);
|
||||
|
||||
ecma_extended_primitive_t *result_value_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t));
|
||||
|
||||
if (JERRY_UNLIKELY (result_value_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
if (sign)
|
||||
{
|
||||
result_value_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN;
|
||||
}
|
||||
|
||||
*ECMA_BIGINT_GET_DIGITS (result_value_p, 0) = digit;
|
||||
return ecma_make_extended_primitive_value (result_value_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_create_from_digit */
|
||||
|
||||
/**
|
||||
* Parse a string and create a BigInt value
|
||||
*
|
||||
@@ -443,17 +471,7 @@ ecma_bigint_to_bigint (ecma_value_t value, /**< any value */
|
||||
}
|
||||
else if (ecma_is_value_true (value))
|
||||
{
|
||||
ecma_extended_primitive_t *result_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t));
|
||||
|
||||
if (result_p != NULL)
|
||||
{
|
||||
*ECMA_BIGINT_GET_DIGITS (result_p, 0) = 1;
|
||||
result = ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
result = ecma_bigint_create_from_digit (1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -911,6 +929,62 @@ ecma_bigint_negate (ecma_extended_primitive_t *value_p) /**< BigInt value */
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_negate */
|
||||
|
||||
/**
|
||||
* Invert all bits of a BigInt value
|
||||
*
|
||||
* @return ecma BigInt value or ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_bigint_unary (ecma_value_t value, /**< BigInt value */
|
||||
ecma_bigint_unary_operation_type type) /**< type of unary operation */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_bigint (value));
|
||||
|
||||
if (value == ECMA_BIGINT_ZERO)
|
||||
{
|
||||
return ecma_bigint_create_from_digit (1, type != ECMA_BIGINT_UNARY_INCREASE);
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value);
|
||||
|
||||
uint32_t sign = (type != ECMA_BIGINT_UNARY_DECREASE) ? ECMA_BIGINT_SIGN : 0;
|
||||
|
||||
if ((value_p->u.bigint_sign_and_size == (uint32_t) (sizeof (ecma_bigint_digit_t) | sign))
|
||||
&& *ECMA_BIGINT_GET_DIGITS (value_p, 0) == 1)
|
||||
{
|
||||
return ECMA_BIGINT_ZERO;
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *result_p;
|
||||
|
||||
if ((value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) == (sign ^ ECMA_BIGINT_SIGN))
|
||||
{
|
||||
result_p = ecma_big_uint_increase (value_p);
|
||||
|
||||
if (type != ECMA_BIGINT_UNARY_INCREASE && result_p != NULL)
|
||||
{
|
||||
result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result_p = ecma_big_uint_decrease (value_p);
|
||||
|
||||
if (type == ECMA_BIGINT_UNARY_INCREASE && result_p != NULL)
|
||||
{
|
||||
result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN;
|
||||
}
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (result_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_unary */
|
||||
|
||||
/**
|
||||
* Add/subtract right BigInt value to/from left BigInt value
|
||||
*
|
||||
|
||||
@@ -38,6 +38,16 @@ typedef enum
|
||||
* return with ECMA_VALUE_NULL instead */
|
||||
} ecma_bigint_parse_string_options_t;
|
||||
|
||||
/**
|
||||
* Types for unary operations
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_BIGINT_UNARY_BITWISE_NOT, /**< bitwise not operation */
|
||||
ECMA_BIGINT_UNARY_INCREASE, /**< increase operation */
|
||||
ECMA_BIGINT_UNARY_DECREASE, /**< decrease operation */
|
||||
} ecma_bigint_unary_operation_type;
|
||||
|
||||
ecma_value_t ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, lit_utf8_size_t size,
|
||||
uint32_t options);
|
||||
ecma_value_t ecma_bigint_parse_string_value (ecma_value_t string, uint32_t options);
|
||||
@@ -54,6 +64,7 @@ int ecma_bigint_compare_to_bigint (ecma_value_t left_value, ecma_value_t right_v
|
||||
int ecma_bigint_compare_to_number (ecma_value_t left_value, ecma_number_t right_value);
|
||||
|
||||
ecma_value_t ecma_bigint_negate (ecma_extended_primitive_t *value_p);
|
||||
ecma_value_t ecma_bigint_unary (ecma_value_t value, ecma_bigint_unary_operation_type type);
|
||||
ecma_value_t ecma_bigint_add_sub (ecma_value_t left_value, ecma_value_t right_value, bool is_add);
|
||||
ecma_value_t ecma_bigint_mul (ecma_value_t left_value, ecma_value_t right_value);
|
||||
ecma_value_t ecma_bigint_div_mod (ecma_value_t left_value, ecma_value_t right_value, bool is_mod);
|
||||
|
||||
Reference in New Issue
Block a user