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:
Zoltan Herczeg
2020-08-10 22:38:34 +02:00
committed by GitHub
parent 43a82cddb9
commit 39fe04814e
11 changed files with 519 additions and 110 deletions
+132
View File
@@ -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,
+85 -11
View File
@@ -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
*
+11
View File
@@ -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);