Fix break and continue generation

This commit is contained in:
Ilmir Usmanov
2014-10-09 20:55:16 +04:00
parent 9cd4344c4e
commit 2c90f8a7f1
2 changed files with 45 additions and 16 deletions
+2 -2
View File
@@ -296,8 +296,8 @@ do { STACK_SET_ELEMENT (NAME, I, (NAME##_stack_value_type) (STACK_ELEMENT(NAME,
#define STACK_DECR_ELEMENT(NAME, I) \
do { STACK_SET_ELEMENT (NAME, I, (NAME##_stack_value_type) (STACK_ELEMENT(NAME, I) - 1)); } while (0)
#define STACK_ITERATE_VARG(NAME, FUNC, ...) \
do { for (NAME##_stack_data_type i = 0; i < NAME.current; i++) { \
#define STACK_ITERATE_VARG(NAME, FUNC, FROM, ...) \
do { for (NAME##_stack_data_type i = FROM; i < NAME.current; i++) { \
FUNC (STACK_ELEMENT (NAME, i), __VA_ARGS__); \
} } while (0)
+43 -14
View File
@@ -533,11 +533,19 @@ rewrite_breaks (opcode_counter_t break_oc, opcode_counter_t dest_oc)
static void
rewrite_continues (opcode_counter_t cont_oc, opcode_counter_t dest_oc)
{
REWRITE_JMP (cont_oc, jmp_up, cont_oc - dest_oc);
if (cont_oc > dest_oc)
{
REWRITE_JMP (cont_oc, jmp_up, cont_oc - dest_oc);
}
else
{
// in case of do-while loop we must jump to condition
REWRITE_JMP (cont_oc, jmp_up, dest_oc - cont_oc);
}
}
static void
rewrite_rewritable_opcodes (rewritable_opcode_type type, opcode_counter_t oc)
rewrite_rewritable_opcodes (rewritable_opcode_type type, uint8_t from, opcode_counter_t oc)
{
STACK_DECLARE_USAGE (U8)
@@ -547,13 +555,13 @@ rewrite_rewritable_opcodes (rewritable_opcode_type type, opcode_counter_t oc)
{
case REWRITABLE_BREAK:
{
STACK_ITERATE_VARG (rewritable_break, rewrite_breaks, oc);
STACK_ITERATE_VARG (rewritable_break, rewrite_breaks, from, oc);
STACK_CLEAN (rewritable_break);
break;
}
case REWRITABLE_CONTINUE:
{
STACK_ITERATE_VARG (rewritable_continue, rewrite_continues, oc);
STACK_ITERATE_VARG (rewritable_continue, rewrite_continues, from, oc);
STACK_CLEAN (rewritable_continue);
break;
}
@@ -2461,6 +2469,7 @@ parse_for_or_for_in_statement (void)
STACK_DECLARE_USAGE (IDX)
STACK_DECLARE_USAGE (U16)
STACK_DECLARE_USAGE (nestings)
STACK_DECLARE_USAGE (U8)
assert_keyword (KW_FOR);
token_after_newlines_must_be (TOK_OPEN_PAREN);
@@ -2548,6 +2557,9 @@ plain_for:
21 jmp_up 5; // step_oc;
22 ...
*/
STACK_PUSH (U8, STACK_SIZE (rewritable_continue));
STACK_PUSH (U8, STACK_SIZE (rewritable_break));
STACK_PUSH (U16, OPCODE_COUNTER ()); // cond_oc;
skip_newlines ();
if (!token_is (TOK_SEMICOLON))
@@ -2585,9 +2597,10 @@ plain_for:
DUMP_OPCODE_2 (jmp_up, 0, OPCODE_COUNTER () - STACK_TOP (U16));
REWRITE_COND_JMP (STACK_HEAD (U16, 3), is_false_jmp_down, OPCODE_COUNTER () - STACK_HEAD (U16, 3));
rewrite_rewritable_opcodes (REWRITABLE_CONTINUE, STACK_TOP (U16));
rewrite_rewritable_opcodes (REWRITABLE_BREAK, OPCODE_COUNTER ());
rewrite_rewritable_opcodes (REWRITABLE_CONTINUE, STACK_HEAD (U8, 2), STACK_TOP (U16));
rewrite_rewritable_opcodes (REWRITABLE_BREAK, STACK_TOP (U8), OPCODE_COUNTER ());
STACK_DROP (U8, 2);
STACK_DROP (IDX, 1);
STACK_DROP (U16, 4);
@@ -2599,6 +2612,7 @@ for_in:
cleanup:
STACK_CHECK_USAGE (IDX);
STACK_CHECK_USAGE (U16);
STACK_CHECK_USAGE (U8);
STACK_CHECK_USAGE (nestings);
}
@@ -2705,29 +2719,33 @@ parse_do_while_statement (void)
// U16 loop_oc;
STACK_DECLARE_USAGE (IDX)
STACK_DECLARE_USAGE (U16)
STACK_DECLARE_USAGE (U8)
STACK_DECLARE_USAGE (nestings)
assert_keyword (KW_DO);
STACK_PUSH (U16, OPCODE_COUNTER ());
STACK_PUSH (U8, STACK_SIZE (rewritable_continue));
STACK_PUSH (U8, STACK_SIZE (rewritable_break));
skip_newlines ();
push_nesting (NESTING_ITERATIONAL);
parse_statement ();
pop_nesting (NESTING_ITERATIONAL);
rewrite_rewritable_opcodes (REWRITABLE_CONTINUE, STACK_HEAD (U8, 2), OPCODE_COUNTER ());
token_after_newlines_must_be_keyword (KW_WHILE);
parse_expression_inside_parens ();
STACK_PUSH (U16, OPCODE_COUNTER ());
DUMP_OPCODE_3 (is_true_jmp_up, INVALID_VALUE, INVALID_VALUE, INVALID_VALUE);
REWRITE_COND_JMP (STACK_HEAD(U16, 1), is_true_jmp_up, OPCODE_COUNTER () - STACK_HEAD (U16, 2));
rewrite_rewritable_opcodes (REWRITABLE_CONTINUE, STACK_HEAD (U16, 2));
rewrite_rewritable_opcodes (REWRITABLE_BREAK, OPCODE_COUNTER ());
rewrite_rewritable_opcodes (REWRITABLE_BREAK, STACK_TOP (U8), OPCODE_COUNTER ());
STACK_DROP (IDX, 1);
STACK_DROP (U16, 2);
STACK_DROP (U16, 1);
STACK_DROP (U8, 2);
STACK_CHECK_USAGE (U8);
STACK_CHECK_USAGE (U16);
STACK_CHECK_USAGE (IDX);
STACK_CHECK_USAGE (nestings);
@@ -2743,10 +2761,14 @@ parse_while_statement (void)
// U16 cond_oc, jmp_oc;
STACK_DECLARE_USAGE (IDX)
STACK_DECLARE_USAGE (U16)
STACK_DECLARE_USAGE (U8)
STACK_DECLARE_USAGE (nestings)
assert_keyword (KW_WHILE);
STACK_PUSH (U8, STACK_SIZE (rewritable_continue));
STACK_PUSH (U8, STACK_SIZE (rewritable_break));
STACK_PUSH (U16, OPCODE_COUNTER ()); // cond_oc;
parse_expression_inside_parens ();
STACK_PUSH (U16, OPCODE_COUNTER ()); // jmp_oc;
@@ -2762,12 +2784,14 @@ parse_while_statement (void)
REWRITE_JMP (STACK_TOP (U16), jmp_up, OPCODE_COUNTER () - STACK_HEAD (U16, 3));
REWRITE_COND_JMP (STACK_HEAD (U16, 2), is_false_jmp_down, OPCODE_COUNTER () - STACK_HEAD (U16, 2));
rewrite_rewritable_opcodes (REWRITABLE_CONTINUE, STACK_HEAD (U16, 3));
rewrite_rewritable_opcodes (REWRITABLE_BREAK, OPCODE_COUNTER ());
rewrite_rewritable_opcodes (REWRITABLE_CONTINUE, STACK_HEAD (U8, 2), STACK_HEAD (U16, 3));
rewrite_rewritable_opcodes (REWRITABLE_BREAK, STACK_TOP (U8), OPCODE_COUNTER ());
STACK_DROP (IDX, 1);
STACK_DROP (U16, 3);
STACK_DROP (U8, 2);
STACK_CHECK_USAGE (U8);
STACK_CHECK_USAGE (U16);
STACK_CHECK_USAGE (IDX);
STACK_CHECK_USAGE (nestings);
@@ -2849,9 +2873,12 @@ parse_switch_statement (void)
STACK_DECLARE_USAGE (rewritable_break)
STACK_DECLARE_USAGE (IDX)
STACK_DECLARE_USAGE (U16)
STACK_DECLARE_USAGE (U8)
assert_keyword (KW_SWITCH);
STACK_PUSH (U8, STACK_SIZE (rewritable_break));
parse_expression_inside_parens ();
token_after_newlines_must_be (TOK_OPEN_BRACE);
push_nesting (NESTING_SWITCH);
@@ -2881,12 +2908,14 @@ parse_switch_statement (void)
EMIT_ERROR ("Expected '}' token");
}
pop_nesting (NESTING_SWITCH);
STACK_DROP (IDX, 1);
rewrite_rewritable_opcodes (REWRITABLE_BREAK, STACK_TOP (U8), OPCODE_COUNTER ());
rewrite_rewritable_opcodes (REWRITABLE_BREAK, OPCODE_COUNTER ());
STACK_DROP (IDX, 1);
STACK_DROP (U8, 1);
STACK_CHECK_USAGE (IDX);
STACK_CHECK_USAGE (U16);
STACK_CHECK_USAGE (U8);
STACK_CHECK_USAGE (rewritable_break);
}