diff --git a/src/libcoreint/opcodes-ecma-arithmetics.c b/src/libcoreint/opcodes-ecma-arithmetics.c index ea2a42d40..c086514ea 100644 --- a/src/libcoreint/opcodes-ecma-arithmetics.c +++ b/src/libcoreint/opcodes-ecma-arithmetics.c @@ -299,3 +299,81 @@ opfunc_remainder (opcode_t opdata, /**< operation data */ return ret_value; } /* opfunc_remainder */ + +/** + * 'Unary "+"' opcode handler. + * + * See also: ECMA-262 v5, 11.4, 11.4.6 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_unary_plus (opcode_t opdata, /**< operation data */ + int_data_t *int_data) /**< interpreter context */ +{ + const idx_t dst_var_idx = opdata.data.remainder.dst; + const idx_t var_idx = opdata.data.remainder.var_left; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (var_value, get_variable_value (int_data, var_idx, false), ret_value); + ECMA_TRY_CATCH (num_value, ecma_op_to_number (var_value.u.value), ret_value); + + ecma_number_t *var_p, *res_p; + var_p = (ecma_number_t*) ECMA_GET_POINTER (num_value.u.value.value); + + res_p = ecma_alloc_number (); + *res_p = *var_p; + ret_value = set_variable_value (int_data, + dst_var_idx, + ecma_make_number_value (res_p)); + + ecma_dealloc_number (res_p); + + ECMA_FINALIZE (num_value); + ECMA_FINALIZE (var_value); + + return ret_value; +} /* opfunc_unary_plus */ + +/** + * 'Unary "-"' opcode handler. + * + * See also: ECMA-262 v5, 11.4, 11.4.7 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_unary_minus (opcode_t opdata, /**< operation data */ + int_data_t *int_data) /**< interpreter context */ +{ + const idx_t dst_var_idx = opdata.data.remainder.dst; + const idx_t var_idx = opdata.data.remainder.var_left; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (var_value, get_variable_value (int_data, var_idx, false), ret_value); + ECMA_TRY_CATCH (num_value, ecma_op_to_number (var_value.u.value), ret_value); + + ecma_number_t *var_p, *res_p; + var_p = (ecma_number_t*) ECMA_GET_POINTER (num_value.u.value.value); + + res_p = ecma_alloc_number (); + *res_p = ecma_number_negate (*var_p); + ret_value = set_variable_value (int_data, + dst_var_idx, + ecma_make_number_value (res_p)); + + ecma_dealloc_number (res_p); + + ECMA_FINALIZE (num_value); + ECMA_FINALIZE (var_value); + + return ret_value; +} /* opfunc_unary_minus */ diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index 9c9f9fe69..66d306818 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -160,7 +160,9 @@ opcode_counter_t read_meta_opcode_counter (opcode_meta_type expected_type, int_d p##_3 (a, substraction, dst, var_left, var_right) \ p##_3 (a, division, dst, var_left, var_right) \ p##_3 (a, multiplication, dst, var_left, var_right) \ - p##_3 (a, remainder, dst, var_left, var_right) + p##_3 (a, remainder, dst, var_left, var_right) \ + p##_2 (a, unary_minus, dst, var) \ + p##_2 (a, unary_plus, dst, var) #define OP_JUMPS(p, a) \ p##_2 (a, jmp_up, opcode_1, opcode_2) \ diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index aac5cb2ac..bfcfc2e7a 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -500,17 +500,6 @@ token_after_newlines_must_be_keyword (keyword kw) } } -static void -integer_zero (void) -{ - STACK_DECLARE_USAGE (IDX) - - STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_SMALLINT, 0); - - STACK_CHECK_USAGE_LHS (); -} - static void boolean_true (void) { @@ -1652,18 +1641,16 @@ parse_unary_expression (void) { STACK_PUSH (IDX, next_temp_name ()); NEXT (unary_expression); - integer_zero (); - DUMP_OPCODE_3 (addition, ID(3), ID(1), ID(2)); - STACK_DROP (IDX, 2); + DUMP_OPCODE_2 (unary_plus, ID(2), ID(1)); + STACK_DROP (IDX, 1); break; } case TOK_MINUS: { STACK_PUSH (IDX, next_temp_name ()); NEXT (unary_expression); - integer_zero (); - DUMP_OPCODE_3 (substraction, ID(3), ID(1), ID(2)); - STACK_DROP (IDX, 2); + DUMP_OPCODE_2 (unary_minus, ID(2), ID(1)); + STACK_DROP (IDX, 1); break; } case TOK_COMPL: diff --git a/src/liboptimizer/pretty-printer.c b/src/liboptimizer/pretty-printer.c index 307663ace..4308ac973 100644 --- a/src/liboptimizer/pretty-printer.c +++ b/src/liboptimizer/pretty-printer.c @@ -215,6 +215,8 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite) PP_OP_3 (division, "%s = %s - %s;", dst, var_left, var_right); PP_OP_3 (multiplication, "%s = %s * %s;", dst, var_left, var_right); PP_OP_3 (remainder, "%s = %s %% %s;", dst, var_left, var_right); + PP_OP_2 (unary_minus, "%s = -%s;", dst, var); + PP_OP_2 (unary_plus, "%s = +%s;", dst, var); PP_OP_3 (b_shift_left, "%s = %s << %s;", dst, var_left, var_right); PP_OP_3 (b_shift_right, "%s = %s >> %s;", dst, var_left, var_right); PP_OP_3 (b_shift_uright, "%s = %s >>> %s;", dst, var_left, var_right); diff --git a/tests/jerry/unary_plus_minus.js b/tests/jerry/unary_plus_minus.js new file mode 100644 index 000000000..874e582d0 --- /dev/null +++ b/tests/jerry/unary_plus_minus.js @@ -0,0 +1,18 @@ +// Copyright 2014 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +assert (+0 === -0); +assert (1/-0 === -Infinity); +assert (1/+0 === Infinity); +assert ("3" -+-+-+ "1" + "1" / "3" * "6" + "2" === "42");