Implementing 'with' opcode; replacing 'end_with' opcode with 'meta' opcode of corresponding type.

This commit is contained in:
Ruben Ayrapetyan 2014-08-27 21:38:53 +04:00
parent f08c242156
commit 5d2b535cec
8 changed files with 93 additions and 14 deletions

View File

@ -45,8 +45,6 @@
*/
#define OP_UNIMPLEMENTED_LIST(op) \
op (with) \
op (end_with) \
static char __unused unimplemented_list_end
#define DEFINE_UNIMPLEMENTED_OP(op) \
@ -1402,6 +1400,68 @@ opfunc_this (opcode_t opdata, /**< operation data */
return ret_value;
} /* opfunc_this */
/**
* 'With' opcode handler.
*
* See also: ECMA-262 v5, 12.10
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_with (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t expr_var_idx = opdata.data.with.expr;
int_data->pos++;
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (expr_value,
get_variable_value (int_data,
expr_var_idx,
false),
ret_value);
ECMA_TRY_CATCH (obj_expr_value,
ecma_op_to_object (expr_value.value),
ret_value);
ecma_object_t *obj_p = ECMA_GET_POINTER (obj_expr_value.value.value);
ecma_object_t *old_env_p = int_data->lex_env_p;
ecma_object_t *new_env_p = ecma_create_object_lex_env (old_env_p,
obj_p,
true);
int_data->lex_env_p = new_env_p;
ecma_completion_value_t evaluation_completion = run_int_loop (int_data);
if (evaluation_completion.type == ECMA_COMPLETION_TYPE_META)
{
opcode_t meta_opcode = read_opcode (int_data->pos);
JERRY_ASSERT (meta_opcode.op_idx == __op__idx_meta);
JERRY_ASSERT (meta_opcode.data.meta.type == OPCODE_META_TYPE_END_WITH);
int_data->pos++;
ret_value = ecma_make_empty_completion_value ();
}
else
{
ret_value = evaluation_completion;
}
int_data->lex_env_p = old_env_p;
ecma_deref_object (new_env_p);
ECMA_FINALIZE (obj_expr_value);
ECMA_FINALIZE (expr_value);
return ret_value;
} /* opfunc_with */
/**
* Evaluate argument of typeof.
*
@ -1682,6 +1742,7 @@ opfunc_meta (opcode_t opdata, /**< operation data */
switch (type)
{
case OPCODE_META_TYPE_VARG:
case OPCODE_META_TYPE_END_WITH:
{
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_META,
ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY),

View File

@ -56,7 +56,8 @@ typedef enum
OPCODE_META_TYPE_VARG, /**< element (var_idx) of arguments' list */
OPCODE_META_TYPE_VARG_PROP_DATA, /**< name (lit_idx) and value (var_idx) for a data property descriptor */
OPCODE_META_TYPE_VARG_PROP_GETTER, /**< name (lit_idx) and getter (var_idx) for an accessor property descriptor */
OPCODE_META_TYPE_VARG_PROP_SETTER /**< name (lit_idx) and setter (var_idx) for an accessor property descriptor */
OPCODE_META_TYPE_VARG_PROP_SETTER, /**< name (lit_idx) and setter (var_idx) for an accessor property descriptor */
OPCODE_META_TYPE_END_WITH /**< end of with statement */
} opcode_meta_type;
typedef struct
@ -95,8 +96,7 @@ typedef struct
p##_2 (a, delete_var, lhs, name) \
p##_3 (a, delete_prop, lhs, base, name) \
p##_2 (a, typeof, lhs, obj) \
p##_1 (a, with, expr) \
p##_0 (a, end_with)
p##_1 (a, with, expr)
#define OP_ASSIGNMENTS(p, a) \
p##_3 (a, assignment, var_left, type_value_right, value_right)

View File

@ -93,7 +93,8 @@ ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< out
ecma_object_t *binding_obj_p, /**< binding object */
bool provide_this) /**< provideThis flag */
{
JERRY_ASSERT(binding_obj_p != NULL);
JERRY_ASSERT(binding_obj_p != NULL
&& !binding_obj_p->is_lexical_environment);
ecma_object_t *new_lexical_environment_p = ecma_alloc_object ();
ecma_init_gc_info (new_lexical_environment_p);

View File

@ -391,7 +391,24 @@ ecma_op_to_string (ecma_value_t value) /**< ecma-value */
ecma_completion_value_t
ecma_op_to_object (ecma_value_t value) /**< ecma-value */
{
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS(value);
switch ((ecma_type_t)value.value_type)
{
case ECMA_TYPE_SIMPLE:
case ECMA_TYPE_NUMBER:
case ECMA_TYPE_STRING:
{
JERRY_UNIMPLEMENTED ();
}
case ECMA_TYPE_OBJECT:
{
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL,
ecma_copy_value (value, true),
ECMA_TARGET_ID_RESERVED);
}
}
JERRY_UNREACHABLE ();
} /* ecma_op_to_object */
/**

View File

@ -36,6 +36,9 @@
ecma_object_t*
ecma_new_standard_error (ecma_standard_error_t error_type) /**< native error type */
{
/* SyntaxError should be treated as an early error */
JERRY_ASSERT (error_type != ECMA_ERROR_SYNTAX);
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS(error_type);
} /* ecma_new_standard_error */

View File

@ -2083,7 +2083,7 @@ parse_with_statement (void)
skip_newlines ();
parse_statement ();
DUMP_VOID_OPCODE (end_with);
DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_END_WITH, INVALID_VALUE, INVALID_VALUE);
}
/* switch_statement

View File

@ -347,8 +347,7 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite)
uint8_t opcode_num = opcode.op_idx;
__printf ("%3d: %20s ", oc, opcode_names[opcode_num]);
if (opcode_num != NAME_TO_ID (nop) && opcode_num != NAME_TO_ID (ret)
&& opcode_num != NAME_TO_ID (end_with))
if (opcode_num != NAME_TO_ID (nop) && opcode_num != NAME_TO_ID (ret))
{
for (i = 1; i < opcode_sizes[opcode_num]; i++)
{
@ -415,7 +414,6 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite)
CASE_EXIT (exitval, "exit", status_code)
CASE_SINGLE_ADDRESS (retval, "return", ret_value)
CASE_ZERO_ADDRESS (ret, "return")
CASE_ZERO_ADDRESS (end_with, "")
CASE_ZERO_ADDRESS (nop, "")
TODO (Refine to match new opcodes)
CASE_VARG_1_LHS (array_decl, lhs, "=", "[", list, "]")

View File

@ -38,8 +38,7 @@ opcodes_equal (const opcode_t *opcodes1, opcode_t *opcodes2, uint16_t size)
if (opcode_num1 != opcode_num2)
return false;
if (opcode_num1 == NAME_TO_ID (nop) || opcode_num1 == NAME_TO_ID (ret)
|| opcode_num1 == NAME_TO_ID (end_with))
if (opcode_num1 == NAME_TO_ID (nop) || opcode_num1 == NAME_TO_ID (ret))
return true;
for (j = 1; j < opcode_sizes[opcode_num1]; j++)
@ -50,4 +49,4 @@ opcodes_equal (const opcode_t *opcodes1, opcode_t *opcodes2, uint16_t size)
return true;
}
#endif // COMMON_H
#endif // COMMON_H