/* 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. */ #include "ecma-comparison.h" #include "ecma-conversion.h" #include "ecma-globals.h" #include "ecma-try-catch-macro.h" #include "globals.h" /** \addtogroup ecma ---TODO--- * @{ * * \addtogroup ecmacomparison ECMA comparison * @{ */ /** * ECMA abstract equality comparison routine. * * See also: ECMA-262 v5, 11.9.3 * * @return true - if values are equal, * false - otherwise. */ bool ecma_op_abstract_equality_compare(ecma_value_t x, /**< first operand */ ecma_value_t y) /**< second operand */ { const bool is_x_undefined = ecma_is_value_undefined( x); const bool is_x_null = ecma_is_value_null( x); const bool is_x_boolean = ecma_is_value_boolean( x); const bool is_x_number = ( x.value_type == ECMA_TYPE_NUMBER ); const bool is_x_string = ( x.value_type == ECMA_TYPE_STRING ); const bool is_x_object = ( x.value_type == ECMA_TYPE_OBJECT ); const bool is_y_undefined = ecma_is_value_undefined( y); const bool is_y_null = ecma_is_value_null( y); const bool is_y_boolean = ecma_is_value_boolean( y); const bool is_y_number = ( y.value_type == ECMA_TYPE_NUMBER ); const bool is_y_string = ( y.value_type == ECMA_TYPE_STRING ); const bool is_y_object = ( y.value_type == ECMA_TYPE_OBJECT ); const bool is_types_equal = ( ( is_x_undefined && is_y_undefined ) || ( is_x_null && is_y_null ) || ( is_x_boolean && is_y_boolean ) || ( is_x_number && is_y_number ) || ( is_x_string && is_y_string ) || ( is_x_object && is_y_object ) ); if ( is_types_equal ) { // 1. if ( is_x_undefined || is_x_null ) { // a., b. return true; } else if ( is_x_number ) { // c. ecma_number_t x_num = *(ecma_number_t*)( ecma_get_pointer(x.value) ); ecma_number_t y_num = *(ecma_number_t*)( ecma_get_pointer(y.value) ); TODO( Implement according to ECMA ); return (x_num == y_num); } else if ( is_x_string ) { // d. ecma_array_first_chunk_t* x_str = (ecma_array_first_chunk_t*)( ecma_get_pointer(x.value) ); ecma_array_first_chunk_t* y_str = (ecma_array_first_chunk_t*)( ecma_get_pointer(y.value) ); return ecma_compare_ecma_string_to_ecma_string( x_str, y_str); } else if ( is_x_boolean ) { // e. return ( x.value == y.value ); } else { // f. JERRY_ASSERT( is_x_object ); return ( x.value == y.value ); } } else if ( ( is_x_null && is_y_undefined ) || ( is_x_undefined && is_y_null ) ) { // 2., 3. return true; } else { JERRY_UNIMPLEMENTED(); } } /* ecma_op_abstract_equality_compare */ /** * ECMA abstract relational comparison routine. * * See also: ECMA-262 v5, 11.8.5 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_abstract_relational_compare(ecma_value_t x, /**< first operand */ ecma_value_t y, /**< second operand */ bool left_first) /**< 'LeftFirst' flag */ { ecma_completion_value_t ret_value, px, py; ecma_value_t first_converted_value = left_first ? x : y; ecma_value_t second_converted_value = left_first ? y : x; // 1., 2. ECMA_TRY_CATCH( prim_first_converted_value, ecma_op_to_primitive( first_converted_value, ECMA_PREFERRED_TYPE_NUMBER), ret_value); ECMA_TRY_CATCH( prim_second_converted_value, ecma_op_to_primitive( second_converted_value, ECMA_PREFERRED_TYPE_NUMBER), ret_value); px = left_first ? prim_first_converted_value : prim_second_converted_value; py = left_first ? prim_second_converted_value : prim_first_converted_value; const bool is_px_string = ( px.value.value_type == ECMA_TYPE_STRING ); const bool is_py_string = ( py.value.value_type == ECMA_TYPE_STRING ); if ( !( is_px_string && is_py_string ) ) { // 3. // a. ECMA_TRY_CATCH( nx, ecma_op_to_number( px.value), ret_value); // b. ECMA_TRY_CATCH( ny, ecma_op_to_number( py.value), ret_value); ecma_number_t* num_x_p = (ecma_number_t*)ecma_get_pointer( nx.value.value); ecma_number_t* num_y_p = (ecma_number_t*)ecma_get_pointer( ny.value.value); TODO( /* Implement according to ECMA */ ); if ( *num_x_p >= *num_y_p ) { ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, ecma_make_simple_value( ECMA_SIMPLE_VALUE_FALSE), ECMA_TARGET_ID_RESERVED); } else { ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, ecma_make_simple_value( ECMA_SIMPLE_VALUE_TRUE), ECMA_TARGET_ID_RESERVED); } ECMA_FINALIZE( ny); ECMA_FINALIZE( nx); } else { // 4. JERRY_UNIMPLEMENTED(); } ECMA_FINALIZE( prim_second_converted_value); ECMA_FINALIZE( prim_first_converted_value); return ret_value; } /* ecma_op_abstract_relational_compare */ /** * @} * @} */