Implement parse of for-in statement.

JerryScript-DCO-1.0-Signed-off-by: Evgeny Gavrin e.gavrin@samsung.com
JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
This commit is contained in:
Ruben Ayrapetyan
2015-06-25 01:20:31 +03:00
parent b988fe2fce
commit 507411f0a0
6 changed files with 540 additions and 9 deletions
+73
View File
@@ -708,6 +708,23 @@ eval_ret_operand (void)
return ret;
} /* eval_ret_operand */
/**
* Creates operand for taking iterator value (next property name)
* from for-in opcode handler.
*
* @return constructed operand
*/
operand
jsp_create_operand_for_in_special_reg (void)
{
operand ret;
ret.type = OPERAND_TMP;
ret.data.uid = OPCODE_REG_SPECIAL_FOR_IN_PROPERTY_NAME;
return ret;
} /* jsp_create_operand_for_in_special_reg */
bool
operand_is_empty (operand op)
{
@@ -2362,6 +2379,62 @@ dump_with_end (void)
serializer_dump_op_meta (create_op_meta_000 (opcode));
} /* dump_with_end */
/**
* Dump template of 'for_in' instruction.
*
* Note:
* the instruction's flags field is written later (see also: rewrite_for_in).
*
* @return position of dumped instruction
*/
opcode_counter_t
dump_for_in_for_rewrite (operand op) /**< operand - result of evaluating Expression
* in for-in statement */
{
opcode_counter_t oc = serializer_get_current_opcode_counter ();
if (op.type == OPERAND_LITERAL)
{
const opcode_t opcode = getop_for_in (LITERAL_TO_REWRITE, INVALID_VALUE, INVALID_VALUE);
serializer_dump_op_meta (create_op_meta_100 (opcode, op.data.lit_id));
}
else
{
JERRY_ASSERT (op.type == OPERAND_TMP);
const opcode_t opcode = getop_for_in (op.data.uid, INVALID_VALUE, INVALID_VALUE);
serializer_dump_op_meta (create_op_meta_000 (opcode));
}
return oc;
} /* dump_for_in_for_rewrite */
/**
* Write position of 'for_in' block's end to specified 'for_in' instruction template,
* dumped earlier (see also: dump_for_in_for_rewrite).
*/
void
rewrite_for_in (opcode_counter_t oc) /**< opcode counter of the instruction template */
{
op_meta for_in_op_meta = serializer_get_op_meta (oc);
idx_t id1, id2;
split_opcode_counter (get_diff_from (oc), &id1, &id2);
for_in_op_meta.op.data.for_in.oc_idx_1 = id1;
for_in_op_meta.op.data.for_in.oc_idx_2 = id2;
serializer_rewrite_op_meta (oc, for_in_op_meta);
} /* rewrite_for_in */
/**
* Dump 'meta' instruction of 'end for_in' type
*/
void
dump_for_in_end (void)
{
const opcode_t opcode = getop_meta (OPCODE_META_TYPE_END_FOR_IN, INVALID_VALUE, INVALID_VALUE);
serializer_dump_op_meta (create_op_meta_000 (opcode));
} /* dump_for_in_end */
void
dump_try_for_rewrite (void)
{
+5
View File
@@ -49,6 +49,7 @@ typedef enum __attr_packed___
operand empty_operand (void);
operand literal_operand (lit_cpointer_t);
operand eval_ret_operand (void);
operand jsp_create_operand_for_in_special_reg (void);
bool operand_is_empty (operand);
void dumper_init (void);
@@ -211,6 +212,10 @@ opcode_counter_t dump_with_for_rewrite (operand);
void rewrite_with (opcode_counter_t);
void dump_with_end (void);
opcode_counter_t dump_for_in_for_rewrite (operand);
void rewrite_for_in (opcode_counter_t);
void dump_for_in_end (void);
void dump_try_for_rewrite (void);
void rewrite_try (void);
void dump_catch_for_rewrite (operand);
+172 -9
View File
@@ -1768,7 +1768,7 @@ parse_expression (bool in_allowed, /**< flag indicating if 'in' is allowed insid
initialiser
: '=' LT!* assignment_expression
; */
static void
static operand
parse_variable_declaration (void)
{
current_token_must_be (TOK_NAME);
@@ -1785,6 +1785,8 @@ parse_variable_declaration (void)
{
lexer_save_token (tok);
}
return name;
}
/* variable_declaration_list
@@ -1933,15 +1935,176 @@ jsp_parse_for_statement (jsp_label_t *outermost_stmt_label_p, /**< outermost (fi
}
} /* jsp_parse_for_statement */
static void
parse_for_in (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label, corresponding to
* the statement (or NULL, if there are no named
* labels associated with the statement) */
/**
* Parse VariableDeclarationNoIn / LeftHandSideExpression (iterator part) of for-in statement
*
* See also:
* jsp_parse_for_in_statement
*
* @return true - if iterator consists of base and property name,
* false - otherwise, iterator consists of an identifier name (without base).
*/
static bool
jsp_parse_for_in_statement_iterator (operand *base_p, /**< out: base value of member expression, if any,
* empty operand - otherwise */
operand *identifier_p) /**< out: property name (if base value is not empty),
* identifier - otherwise */
{
(void) outermost_stmt_label_p;
JERRY_ASSERT (base_p != NULL);
JERRY_ASSERT (identifier_p != NULL);
EMIT_SORRY ("'for in' loops are not supported yet");
}
if (is_keyword (KW_VAR))
{
skip_newlines ();
*base_p = empty_operand ();
*identifier_p = parse_variable_declaration ();
return false;
}
else
{
operand base, identifier;
/*
* FIXME:
* Remove evaluation of last part of identifier chain
*/
operand i = parse_left_hand_side_expression (&base, &identifier);
if (operand_is_empty (base))
{
*base_p = empty_operand ();
*identifier_p = i;
return false;
}
else
{
*base_p = base;
*identifier_p = identifier;
return true;
}
}
} /* jsp_parse_for_in_statement_iterator */
/**
* Parse for-in statement
*
* See also:
* ECMA-262 v5, 12.6.4
*
* Note:
* Syntax:
* Iterator Collection Body LoopEnd
* - for ( LeftHandSideExpression in Expression) Statement
* - for (var VariableDeclarationNoIn in Expression) Statement
*
* Note:
* Layout of generate byte-code is the following:
* tmp <- Collection (Expression)
* for_in instruction (tmp, opcode counter of for-in end mark)
* {
* Assignment of OPCODE_REG_SPECIAL_FOR_IN_PROPERTY_NAME to
* Iterator (VariableDeclarationNoIn / LeftHandSideExpression)
* }
* Body (Statement)
* ContinueTarget:
* meta (OPCODE_META_TYPE_END_FOR_IN)
*/
static void
jsp_parse_for_in_statement (jsp_label_t *outermost_stmt_label_p, /**< outermost (first) label,
* corresponding to the statement
* (or NULL, if there are no name
* labels associated with the statement) */
locus for_body_statement_loc) /**< locus of loop body statement */
{
jsp_label_raise_nested_jumpable_border ();
current_token_must_be (TOK_OPEN_PAREN);
skip_newlines ();
// Save Iterator location
locus iterator_loc = tok.loc;
while (tok.loc < for_body_statement_loc)
{
if (jsp_find_next_token_before_the_locus (TOK_KEYWORD,
for_body_statement_loc,
true))
{
if (is_keyword (KW_IN))
{
break;
}
else
{
skip_token ();
}
}
else
{
EMIT_ERROR ("Invalid for statement");
}
}
JERRY_ASSERT (is_keyword (KW_IN));
skip_newlines ();
// Collection
operand collection = parse_expression (true, JSP_EVAL_RET_STORE_NOT_DUMP);
current_token_must_be (TOK_CLOSE_PAREN);
skip_token ();
// Dump for-in instruction
opcode_counter_t for_in_oc = dump_for_in_for_rewrite (collection);
// Dump assignment VariableDeclarationNoIn / LeftHandSideExpression <- OPCODE_REG_SPECIAL_FOR_IN_PROPERTY_NAME
lexer_seek (iterator_loc);
tok = lexer_next_token ();
operand iterator_base, iterator_identifier, for_in_special_reg;
for_in_special_reg = jsp_create_operand_for_in_special_reg ();
if (jsp_parse_for_in_statement_iterator (&iterator_base, &iterator_identifier))
{
dump_prop_setter (iterator_base, iterator_identifier, for_in_special_reg);
}
else
{
JERRY_ASSERT (operand_is_empty (iterator_base));
dump_variable_assignment (iterator_identifier, for_in_special_reg);
}
// Body
lexer_seek (for_body_statement_loc);
tok = lexer_next_token ();
parse_statement (NULL);
// Save LoopEnd locus
const locus loop_end_loc = tok.loc;
// Setup ContinueTarget
jsp_label_setup_continue_target (outermost_stmt_label_p,
serializer_get_current_opcode_counter ());
// Write position of for-in end to for_in instruction
rewrite_for_in (for_in_oc);
// Dump meta (OPCODE_META_TYPE_END_FOR_IN)
dump_for_in_end ();
lexer_seek (loop_end_loc);
tok = lexer_next_token ();
if (tok.type != TOK_CLOSE_BRACE)
{
lexer_save_token (tok);
}
jsp_label_remove_nested_jumpable_border ();
} /* jsp_parse_for_in_statement */
/**
* Parse for/for-in statements
@@ -1982,7 +2145,7 @@ jsp_parse_for_or_for_in_statement (jsp_label_t *outermost_stmt_label_p) /**< out
}
else
{
parse_for_in (outermost_stmt_label_p);
jsp_parse_for_in_statement (outermost_stmt_label_p, for_body_statement_loc);
}
} /* jsp_parse_for_or_for_in_statement */
+1
View File
@@ -306,6 +306,7 @@ generate_opcode (scopes_tree tree, opcode_counter_t opc_index, lit_id_hash_table
case OPCODE (obj_decl):
case OPCODE (this_binding):
case OPCODE (with):
case OPCODE (for_in):
case OPCODE (throw_value):
case OPCODE (is_true_jmp_up):
case OPCODE (is_true_jmp_down):