From 5373b609559261954903d85a42da8016562ce3c6 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Mon, 11 Aug 2014 23:17:45 +0400 Subject: [PATCH] Reformat --- src/libcoreint/opcodes.h | 172 ++-- src/libjsparser/lexer.c | 991 +++++++++++++++++------- src/libjsparser/lexer.h | 116 +-- src/libjsparser/parser.c | 1594 ++++++++++++++++++++------------------ tests/jerry/N.for.js | 35 + 5 files changed, 1734 insertions(+), 1174 deletions(-) create mode 100644 tests/jerry/N.for.js diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index 7fee3c370..8a7f328dc 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -36,114 +36,114 @@ OPCODE; typedef ecma_completion_value_t (*opfunc)(OPCODE, struct __int_data *); #define OP_CALLS_AND_ARGS(op) \ - op(call_0) \ - op(call_1) \ - op(call_n) \ - op(construct_0) \ - op(construct_1) \ - op(construct_n) \ - op(func_decl_0) \ - op(func_decl_1) \ - op(func_decl_2) \ - op(func_decl_n) \ - op(func_expr_0) \ - op(func_expr_1) \ - op(func_expr_n) \ - op(varg_1_end) \ - op(varg_2_end) \ - op(varg_3) \ - op(varg_3_end) \ - op(exitval) \ - op(retval) \ - op(ret) + op (call_0) \ + op (call_1) \ + op (call_n) \ + op (construct_0) \ + op (construct_1) \ + op (construct_n) \ + op (func_decl_0) \ + op (func_decl_1) \ + op (func_decl_2) \ + op (func_decl_n) \ + op (func_expr_0) \ + op (func_expr_1) \ + op (func_expr_n) \ + op (varg_1_end) \ + op (varg_2_end) \ + op (varg_3) \ + op (varg_3_end) \ + op (exitval) \ + op (retval) \ + op (ret) #define OP_INITS(op) \ - op(array_0) \ - op(array_1) \ - op(array_2) \ - op(array_n) \ - op(prop) \ - op(prop_access) \ - op(prop_get_decl) \ - op(prop_set_decl) \ - op(obj_0) \ - op(obj_1) \ - op(obj_2) \ - op(obj_n) \ - op(this) \ - op(delete) \ - op(typeof) \ - op(with) \ - op(end_with) + op (array_0) \ + op (array_1) \ + op (array_2) \ + op (array_n) \ + op (prop) \ + op (prop_access) \ + op (prop_get_decl) \ + op (prop_set_decl) \ + op (obj_0) \ + op (obj_1) \ + op (obj_2) \ + op (obj_n) \ + op (this) \ + op (delete) \ + op (typeof) \ + op (with) \ + op (end_with) #define OP_ASSIGNMENTS(op) \ - op(assignment) + op (assignment) #define OP_B_SHIFTS(op) \ - op(b_shift_left) \ - op(b_shift_right) \ - op(b_shift_uright) + op (b_shift_left) \ + op (b_shift_right) \ + op (b_shift_uright) #define OP_B_BITWISE(op) \ - op(b_and) \ - op(b_or) \ - op(b_xor) \ - op(b_not) + op (b_and) \ + op (b_or) \ + op (b_xor) \ + op (b_not) #define OP_B_LOGICAL(op) \ - op(logical_and) \ - op(logical_or) \ - op(logical_not) + op (logical_and) \ + op (logical_or) \ + op (logical_not) #define OP_EQUALITY(op) \ - op(equal_value) \ - op(not_equal_value) \ - op(equal_value_type) \ - op(not_equal_value_type) + op (equal_value) \ + op (not_equal_value) \ + op (equal_value_type) \ + op (not_equal_value_type) #define OP_RELATIONAL(op) \ - op(less_than) \ - op(greater_than) \ - op(less_or_equal_than) \ - op(greater_or_equal_than) \ - op(instanceof) \ - op(in) + op (less_than) \ + op (greater_than) \ + op (less_or_equal_than) \ + op (greater_or_equal_than) \ + op (instanceof) \ + op (in) #define OP_ARITHMETIC(op) \ - op(post_incr) \ - op(post_decr) \ - op(pre_incr) \ - op(pre_decr) \ - op(addition) \ - op(substraction) \ - op(division) \ - op(multiplication) \ - op(remainder) + op (post_incr) \ + op (post_decr) \ + op (pre_incr) \ + op (pre_decr) \ + op (addition) \ + op (substraction) \ + op (division) \ + op (multiplication) \ + op (remainder) #define OP_UNCONDITIONAL_JUMPS(op) \ - op(jmp) \ - op(jmp_up) \ - op(jmp_down) \ - op(nop) + op (jmp) \ + op (jmp_up) \ + op (jmp_down) \ + op (nop) #define OP_UNARY_OPS(op) \ - op(is_true_jmp) \ - op(is_false_jmp) + op (is_true_jmp) \ + op (is_false_jmp) #define OP_LIST(op) \ - OP_CALLS_AND_ARGS(op) \ - OP_INITS(op) \ - OP_ASSIGNMENTS(op) \ - OP_B_LOGICAL(op) \ - OP_B_BITWISE(op) \ - OP_B_SHIFTS(op) \ - OP_EQUALITY(op) \ - OP_RELATIONAL(op) \ - OP_ARITHMETIC(op) \ - OP_UNCONDITIONAL_JUMPS(op) \ - OP_UNARY_OPS(op) \ - op(var_decl) \ - op(reg_var_decl) + OP_CALLS_AND_ARGS (op) \ + OP_INITS (op) \ + OP_ASSIGNMENTS (op) \ + OP_B_LOGICAL (op) \ + OP_B_BITWISE (op) \ + OP_B_SHIFTS (op) \ + OP_EQUALITY (op) \ + OP_RELATIONAL (op) \ + OP_ARITHMETIC (op) \ + OP_UNCONDITIONAL_JUMPS (op) \ + OP_UNARY_OPS (op) \ + op (var_decl) \ + op (reg_var_decl) #include "opcode-structures.h" diff --git a/src/libjsparser/lexer.c b/src/libjsparser/lexer.c index 3550d8249..0e4da1cb3 100644 --- a/src/libjsparser/lexer.c +++ b/src/libjsparser/lexer.c @@ -35,7 +35,7 @@ num_and_token; static uint8_t seen_names_count = 0; -static num_and_token seen_nums[MAX_NUMS] = +static num_and_token seen_nums[MAX_NUMS] = { [0] = { .num = 0, .tok = { .type = TOK_INT, .data.uid = 0 } }, [1] = { .num = 1, .tok = { .type = TOK_INT, .data.uid = 1 } } @@ -57,7 +57,9 @@ static char get_char (size_t i) { if ((buffer + i) >= (buffer_start + buffer_size)) + { return '\0'; + } return *(buffer + i); } @@ -73,25 +75,27 @@ increase_strings_cache (void) char *new_cache; size_t new_cache_size; - // if strings_cache_size == 0, allocator recommend minimum size that is more than 0 + // if strings_cache_size == 0, allocator recommends minimum size that is more than 0 new_cache_size = mem_heap_recommend_allocation_size (strings_cache_size * 2); new_cache = (char *) mem_heap_alloc_block (new_cache_size, MEM_HEAP_ALLOC_SHORT_TERM); if (!new_cache) - { - // Allocator alligns recommended memory size - new_cache_size = mem_heap_recommend_allocation_size (strings_cache_size + 1); - new_cache = (char *) mem_heap_alloc_block (new_cache_size, MEM_HEAP_ALLOC_SHORT_TERM); + { + // Allocator alligns recommended memory size + new_cache_size = mem_heap_recommend_allocation_size (strings_cache_size + 1); + new_cache = (char *) mem_heap_alloc_block (new_cache_size, MEM_HEAP_ALLOC_SHORT_TERM); - if (!new_cache) - parser_fatal (ERR_MEMORY); + if (!new_cache) + { + parser_fatal (ERR_MEMORY); } + } if (strings_cache) - { - __memcpy (new_cache, strings_cache, strings_cache_size); - mem_heap_free_block ((uint8_t *) strings_cache); - } + { + __memcpy (new_cache, strings_cache, strings_cache_size); + mem_heap_free_block ((uint8_t *) strings_cache); + } strings_cache = new_cache; strings_cache_size = new_cache_size; @@ -104,12 +108,16 @@ dump_current_line (void) const char *i; if (!allow_dump_lines) + { return; + } __printf ("// "); for (i = buffer; *i != '\n' && *i != 0; i++) + { __putchar (*i); + } __putchar ('\n'); } #endif @@ -118,9 +126,13 @@ static bool current_token_equals_to (const char *str) { if (__strlen (str) != (size_t) (buffer - token_start)) + { return false; + } if (!__strncmp (str, token_start, (size_t) (buffer - token_start))) + { return true; + } return false; } @@ -131,95 +143,365 @@ static token decode_keyword (void) { if (current_token_equals_to ("break")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_BREAK }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_BREAK + }; + } if (current_token_equals_to ("case")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_CASE }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_CASE + }; + } if (current_token_equals_to ("catch")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_CATCH }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_CATCH + }; + } if (current_token_equals_to ("class")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("const")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("continue")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_CONTINUE }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_CONTINUE + }; + } if (current_token_equals_to ("debugger")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_DEBUGGER }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_DEBUGGER + }; + } if (current_token_equals_to ("default")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_DEFAULT }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_DEFAULT + }; + } if (current_token_equals_to ("delete")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_DELETE }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_DELETE + }; + } if (current_token_equals_to ("do")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_DO }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_DO + }; + } if (current_token_equals_to ("else")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_ELSE }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_ELSE + }; + } if (current_token_equals_to ("enum")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("export")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("extends")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("false")) - return (token) { .type = TOK_BOOL, .data.uid = false }; + { + return (token) + { + .type = TOK_BOOL, + .data.uid = false + }; + } if (current_token_equals_to ("finally")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_FINALLY }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_FINALLY + }; + } if (current_token_equals_to ("for")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_FOR }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_FOR + }; + } if (current_token_equals_to ("function")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_FUNCTION }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_FUNCTION + }; + } if (current_token_equals_to ("if")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_IF }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_IF + }; + } if (current_token_equals_to ("instanceof")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_INSTANCEOF }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_INSTANCEOF + }; + } if (current_token_equals_to ("interface")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("in")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_IN }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_IN + }; + } if (current_token_equals_to ("import")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("implements")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("let")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("new")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_NEW }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_NEW + }; + } if (current_token_equals_to ("null")) - return (token) { .type = TOK_NULL, .data.uid = 0 }; + { + return (token) + { + .type = TOK_NULL, + .data.uid = 0 + }; + } if (current_token_equals_to ("package")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("private")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("protected")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("public")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("return")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RETURN }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RETURN + }; + } if (current_token_equals_to ("static")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("super")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } if (current_token_equals_to ("switch")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_SWITCH }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_SWITCH + }; + } if (current_token_equals_to ("this")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_THIS }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_THIS + }; + } if (current_token_equals_to ("throw")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_THROW }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_THROW + }; + } if (current_token_equals_to ("true")) - return (token) { .type = TOK_BOOL, .data.uid = true }; + { + return (token) + { + .type = TOK_BOOL, + .data.uid = true + }; + } if (current_token_equals_to ("try")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_TRY }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_TRY + }; + } if (current_token_equals_to ("typeof")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_TYPEOF }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_TYPEOF + }; + } if (current_token_equals_to ("var")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_VAR }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_VAR + }; + } if (current_token_equals_to ("void")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_VOID }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_VOID + }; + } if (current_token_equals_to ("while")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_WHILE }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_WHILE + }; + } if (current_token_equals_to ("with")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_WITH }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_WITH + }; + } if (current_token_equals_to ("yield")) - return (token) { .type = TOK_KEYWORD, .data.kw = KW_RESERVED }; + { + return (token) + { + .type = TOK_KEYWORD, + .data.kw = KW_RESERVED + }; + } return empty_token; } @@ -231,16 +513,20 @@ convert_seen_name_to_token (token_type tt, const char *string) JERRY_ASSERT (strings_cache); for (i = 0; i < seen_names_count; i++) + { + if ((string == NULL && current_token_equals_to (current_string)) + || (string != NULL && !__strcmp (current_string, string))) { - if ((string == NULL && current_token_equals_to (current_string)) - || (string != NULL && !__strcmp (current_string, string))) - { - return (token) { .type = tt, .data.uid = i }; - } - - current_string += __strlen (current_string) + 1; + return (token) + { + .type = tt, + .data.uid = i + }; } + current_string += __strlen (current_string) + 1; + } + return empty_token; } @@ -254,31 +540,37 @@ add_token_to_seen_names (token_type tt, const char *string) // Go to unused memory of cache for (i = 0; i < seen_names_count; i++) + { current_string += __strlen (current_string) + 1; + } required_size = (size_t) (current_string - strings_cache) + len + 1; if (required_size > strings_cache_size) - { - size_t offset = (size_t) (current_string - strings_cache); - increase_strings_cache (); + { + size_t offset = (size_t) (current_string - strings_cache); + increase_strings_cache (); - // Now our pointer are invalid, adjust it - current_string = strings_cache + offset; - } + // Now our pointer are invalid, adjust it + current_string = strings_cache + offset; + } if (string == NULL) - { - // Copy current token with terminating NULL - __strncpy (current_string, token_start, (size_t) (buffer - token_start)); - current_string += buffer - token_start; - *current_string = '\0'; - } + { + // Copy current token with terminating NULL + __strncpy (current_string, token_start, (size_t) (buffer - token_start)); + current_string += buffer - token_start; + *current_string = '\0'; + } else - { - __memcpy (current_string, string, __strlen (string) + 1); - } + { + __memcpy (current_string, string, __strlen (string) + 1); + } - return (token) { .type = tt, .data.uid = seen_names_count++ }; + return (token) + { + .type = tt, + .data.uid = seen_names_count++ + }; } static token @@ -287,10 +579,12 @@ convert_seen_num_to_token (int num) size_t i; for (i = 0; i < seen_nums_count; i++) + { + if (seen_nums[i].num == num) { - if (seen_nums[i].num == num) - return seen_nums[i].tok; + return seen_nums[i].tok; } + } return empty_token; } @@ -307,15 +601,15 @@ uint8_t lexer_get_strings (const char **strings) { if (strings) + { + char *current_string = strings_cache; + int i; + for (i = 0; i < seen_names_count; i++) { - char *current_string = strings_cache; - int i; - for (i = 0; i < seen_names_count; i++) - { - strings[i] = current_string; - current_string += __strlen (current_string) + 1; - } + strings[i] = current_string; + current_string += __strlen (current_string) + 1; } + } return seen_names_count; } @@ -334,7 +628,9 @@ lexer_get_string_by_id (uint8_t id) JERRY_ASSERT (id < seen_names_count); for (i = 0 ; i < id; i++) + { current_string += __strlen (current_string) + 1; + } return current_string; } @@ -345,10 +641,14 @@ lexer_get_nums (int32_t *nums) int i; if (!nums) + { return seen_nums_count; + } for (i = 0; i < seen_nums_count; i++) + { nums[i] = seen_nums[i].num; + } return seen_nums_count; } @@ -359,7 +659,9 @@ lexer_adjust_num_ids (void) size_t i; for (i = 0; i < seen_nums_count; i++) + { seen_nums[i].tok.data.uid = (uint8_t) (seen_nums[i].tok.data.uid + seen_names_count); + } } static void @@ -378,37 +680,51 @@ consume_char (void) #define RETURN_PUNC_EX(TOK, NUM) \ do \ + { \ + buffer += NUM; \ + return (token) \ { \ - buffer += NUM; \ - return (token) { .type = TOK, .data.uid = 0 }; \ - } \ + .type = TOK, \ + .data.uid = 0 \ + }; \ + } \ while (0) #define RETURN_PUNC(TOK) RETURN_PUNC_EX(TOK, 1) -#define IF_LA_N_IS(CHAR, THEN_TOK, ELSE_TOK, NUM) \ +#define IF_LA_N_IS(CHAR, THEN_TOK, ELSE_TOK, NUM) \ do \ + { \ + if (LA (NUM) == CHAR) \ { \ - if (LA (NUM) == CHAR) \ - RETURN_PUNC_EX (THEN_TOK, NUM + 1); \ - else \ - RETURN_PUNC_EX (ELSE_TOK, NUM); \ + RETURN_PUNC_EX (THEN_TOK, NUM + 1); \ } \ + else \ + { \ + RETURN_PUNC_EX (ELSE_TOK, NUM); \ + } \ + } \ while (0) -#define IF_LA_IS(CHAR, THEN_TOK, ELSE_TOK) \ +#define IF_LA_IS(CHAR, THEN_TOK, ELSE_TOK) \ IF_LA_N_IS (CHAR, THEN_TOK, ELSE_TOK, 1) -#define IF_LA_IS_OR(CHAR1, THEN1_TOK, CHAR2, THEN2_TOK, ELSE_TOK) \ +#define IF_LA_IS_OR(CHAR1, THEN1_TOK, CHAR2, THEN2_TOK, ELSE_TOK) \ do \ + { \ + if (LA (1) == CHAR1) \ { \ - if (LA (1) == CHAR1) \ - RETURN_PUNC_EX (THEN1_TOK, 2); \ - else if (LA (1) == CHAR2) \ - RETURN_PUNC_EX (THEN2_TOK, 2); \ - else \ - RETURN_PUNC (ELSE_TOK); \ + RETURN_PUNC_EX (THEN1_TOK, 2); \ } \ + else if (LA (1) == CHAR2) \ + { \ + RETURN_PUNC_EX (THEN2_TOK, 2); \ + } \ + else \ + { \ + RETURN_PUNC (ELSE_TOK); \ + } \ + } \ while (0) static token @@ -423,28 +739,38 @@ parse_name (void) new_token (); consume_char (); while (true) + { + c = LA (0); + if (c == '\0') { - c = LA (0); - if (c == '\0') - break; - if (!__isalpha (c) && !__isdigit (c) && c != '$' && c != '_') - break; - if (every_char_islower && (!__islower (c))) - every_char_islower = false; - consume_char (); + break; } + if (!__isalpha (c) && !__isdigit (c) && c != '$' && c != '_') + { + break; + } + if (every_char_islower && (!__islower (c))) + { + every_char_islower = false; + } + consume_char (); + } if (every_char_islower) + { + known_token = decode_keyword (); + if (!is_empty (known_token)) { - known_token = decode_keyword (); - if (!is_empty (known_token)) - goto end; + goto end; } + } known_token = convert_seen_name_to_token (TOK_NAME, NULL); if (!is_empty (known_token)) + { goto end; - + } + known_token = add_token_to_seen_names (TOK_NAME, NULL); end: @@ -467,17 +793,17 @@ hex_to_int (char hex) case '7': return 0x7; case '8': return 0x8; case '9': return 0x9; - case 'a': + case 'a': case 'A': return 0xA; - case 'b': + case 'b': case 'B': return 0xB; - case 'c': + case 'c': case 'C': return 0xC; - case 'd': + case 'd': case 'D': return 0xD; - case 'e': + case 'e': case 'E': return 0xE; - case 'f': + case 'f': case 'F': return 0xF; default: JERRY_UNREACHABLE (); } @@ -499,113 +825,157 @@ parse_number (void) JERRY_ASSERT (__isdigit (c) || c == '.'); if (c == '0') + { if (LA (1) == 'x' || LA (1) == 'X') + { is_hex = true; + } + } if (c == '.') - { - JERRY_ASSERT (!__isalpha (LA (1))); - is_fp = true; - } + { + JERRY_ASSERT (!__isalpha (LA (1))); + is_fp = true; + } if (is_hex) + { + // Eat up '0x' + consume_char (); + consume_char (); + new_token (); + while (true) { - // Eat up '0x' + c = LA (0); + if (!__isxdigit (c)) + { + break; + } consume_char (); - consume_char (); - new_token (); - while (true) - { - c = LA (0); - if (!__isxdigit (c)) - break; - consume_char (); - } + } - if (__isalpha (c) || c == '_' || c == '$') - parser_fatal (ERR_INT_LITERAL); + if (__isalpha (c) || c == '_' || c == '$') + { + parser_fatal (ERR_INT_LITERAL); + } - tok_length = (size_t) (buffer - token_start); - // OK, I know that integer overflow can occur here - for (i = 0; i < tok_length; i++) - res = (res << 4) + hex_to_int (token_start[i]); + tok_length = (size_t) (buffer - token_start); + // OK, I know that integer overflow can occur here + for (i = 0; i < tok_length; i++) + { + res = (res << 4) + hex_to_int (token_start[i]); + } - token_start = NULL; + token_start = NULL; - known_token = convert_seen_num_to_token (res); - if (!is_empty (known_token)) - return known_token; - - known_token = (token) { .type = TOK_INT, .data.uid = seen_nums_count }; - add_num_to_seen_tokens ((num_and_token) { .num = res, .tok = known_token }); + known_token = convert_seen_num_to_token (res); + if (!is_empty (known_token)) + { return known_token; } + known_token = (token) + { + .type = TOK_INT, .data.uid = seen_nums_count + }; + add_num_to_seen_tokens ((num_and_token) + { + .num = res, .tok = known_token + }); + return known_token; + } + JERRY_ASSERT (!is_hex && !is_exp); new_token (); // Eat up '.' if (is_fp) + { consume_char (); + } while (true) + { + c = LA (0); + if (is_fp && c == '.') { - c = LA (0); - if (is_fp && c == '.') - parser_fatal (ERR_INT_LITERAL); - if (is_exp && (c == 'e' || c == 'E')) - parser_fatal (ERR_INT_LITERAL); - - if (c == '.') - { - if (__isalpha (LA (1)) || LA (1) == '_' || LA (1) == '$') - parser_fatal (ERR_INT_LITERAL); - is_fp = true; - consume_char (); - continue; - } - - if (c == 'e' || c == 'E') - { - if (LA (1) == '-' || LA (1) == '+') - consume_char (); - if (!__isdigit (LA (1))) - parser_fatal (ERR_INT_LITERAL); - is_exp = true; - consume_char (); - continue; - } - - if (__isalpha (c) || c == '_' || c == '$') - parser_fatal (ERR_INT_LITERAL); - - if (!__isdigit (c)) - break; - - consume_char (); + parser_fatal (ERR_INT_LITERAL); } + if (is_exp && (c == 'e' || c == 'E')) + { + parser_fatal (ERR_INT_LITERAL); + } + + if (c == '.') + { + if (__isalpha (LA (1)) || LA (1) == '_' || LA (1) == '$') + { + parser_fatal (ERR_INT_LITERAL); + } + is_fp = true; + consume_char (); + continue; + } + + if (c == 'e' || c == 'E') + { + if (LA (1) == '-' || LA (1) == '+') + { + consume_char (); + } + if (!__isdigit (LA (1))) + { + parser_fatal (ERR_INT_LITERAL); + } + is_exp = true; + consume_char (); + continue; + } + + if (__isalpha (c) || c == '_' || c == '$') + { + parser_fatal (ERR_INT_LITERAL); + } + + if (!__isdigit (c)) + { + break; + } + + consume_char (); + } if (is_fp || is_exp) - { - float res = __strtof (token_start, NULL); - token_start = NULL; - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (res); - return empty_token; - } + { + float res = __strtof (token_start, NULL); + token_start = NULL; + JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (res); + return empty_token; + } tok_length = (size_t) (buffer - token_start);; for (i = 0; i < tok_length; i++) + { res = res * 10 + hex_to_int (token_start[i]); + } token_start = NULL; known_token = convert_seen_num_to_token (res); if (!is_empty (known_token)) + { return known_token; + } - known_token = (token) { .type = TOK_INT, .data.uid = seen_nums_count }; - add_num_to_seen_tokens ((num_and_token) { .num = res, .tok = known_token }); + known_token = (token) + { + .type = TOK_INT, .data.uid = seen_nums_count + }; + add_num_to_seen_tokens ((num_and_token) + { + .num = res, .tok = known_token + }); return known_token; } @@ -647,64 +1017,74 @@ parse_string (void) new_token (); while (true) + { + c = LA (0); + if (c == '\0') { - c = LA (0); - if (c == '\0') - parser_fatal (ERR_UNCLOSED); - if (c == '\n') - parser_fatal (ERR_STRING); - if (c == '\\') - { - /* Only single escape character is allowed. */ - if (LA (1) == 'x' || LA (1) == 'u' || __isdigit (LA (1))) - parser_fatal (ERR_STRING); - if ((LA (1) == '\'' && !is_double_quoted) - || (LA (1) == '"' && is_double_quoted) - || LA (1) == '\n') - { - consume_char (); - consume_char (); - continue; - } - } - else if ((c == '\'' && !is_double_quoted) - || (c == '"' && is_double_quoted)) - break; - - consume_char (); + parser_fatal (ERR_UNCLOSED); } + if (c == '\n') + { + parser_fatal (ERR_STRING); + } + if (c == '\\') + { + /* Only single escape character is allowed. */ + if (LA (1) == 'x' || LA (1) == 'u' || __isdigit (LA (1))) + { + parser_fatal (ERR_STRING); + } + if ((LA (1) == '\'' && !is_double_quoted) + || (LA (1) == '"' && is_double_quoted) + || LA (1) == '\n') + { + consume_char (); + consume_char (); + continue; + } + } + else if ((c == '\'' && !is_double_quoted) + || (c == '"' && is_double_quoted)) + { + break; + } + + consume_char (); + } length = (size_t) (buffer - token_start); tok = (char *) mem_heap_alloc_block (length + 1, MEM_HEAP_ALLOC_SHORT_TERM); __memset (tok, '\0', length + 1); index = tok; - // Copy current token to TOK and replace escape sequences by there meanings + // Copy current token to TOK and replace escape sequences by there meanings for (i = token_start; i < buffer; i++) + { + if (*i == '\\') { - if (*i == '\\') - { - if (*(i+1) == '\n') - { - i++; - continue; - } - *index = escape_char (*(i+1)); - index++; - i++; - continue; - } - - *index = *i; + if (*(i+1) == '\n') + { + i++; + continue; + } + *index = escape_char (*(i+1)); index++; + i++; + continue; } + *index = *i; + index++; + } + // Eat up '"' consume_char (); known_token = convert_seen_name_to_token (TOK_STRING, tok); if (!is_empty (known_token)) + { goto end; + } known_token = add_token_to_seen_names (TOK_STRING, tok); @@ -720,10 +1100,10 @@ grobble_whitespaces (void) char c = LA (0); while ((__isspace (c) && c != '\n')) - { - consume_char (); - c = LA (0); - } + { + consume_char (); + c = LA (0); + } } static void @@ -734,9 +1114,9 @@ lexer_set_source (const char * source) } static void -lexer_rewind( void) +lexer_rewind (void) { - JERRY_ASSERT( buffer_start != NULL ); + JERRY_ASSERT (buffer_start != NULL); buffer = buffer_start; } @@ -757,25 +1137,35 @@ replace_comment_by_newline (void) consume_char (); while (true) + { + c = LA (0); + if (!multiline && (c == '\n' || c == '\0')) { - c = LA (0); - if (!multiline && (c == '\n' || c == '\0')) - return false; - if (multiline && c == '*' && LA (1) == '/') - { - consume_char (); - consume_char (); - if (was_newlines) - return true; - else - return false; - } - if (multiline && c == '\n') - was_newlines = true; - if (multiline && c == '\0') - parser_fatal (ERR_UNCLOSED); - consume_char (); + return false; } + if (multiline && c == '*' && LA (1) == '/') + { + consume_char (); + consume_char (); + if (was_newlines) + { + return true; + } + else + { + return false; + } + } + if (multiline && c == '\n') + { + was_newlines = true; + } + if (multiline && c == '\0') + { + parser_fatal (ERR_UNCLOSED); + } + consume_char (); + } } static token @@ -784,51 +1174,75 @@ lexer_next_token_private (void) char c = LA (0); if (!is_empty (saved_token)) - { - token res = saved_token; - saved_token = empty_token; - return res; - } + { + token res = saved_token; + saved_token = empty_token; + return res; + } JERRY_ASSERT (token_start == NULL); if (__isalpha (c) || c == '$' || c == '_') + { return parse_name (); + } if (__isdigit (c) || (c == '.' && __isdigit (LA (1)))) + { return parse_number (); + } if (c == '\n') + { + consume_char (); + return (token) { - consume_char (); - return (token) { .type = TOK_NEWLINE, .data.uid = 0 }; - } + .type = TOK_NEWLINE, + .data.uid = 0 + }; + } if (c == '\0') - return (token) { .type = TOK_EOF, .data.uid = 0 };; + { + return (token) + { + .type = TOK_EOF, + .data.uid = 0 + }; + } if (c == '\'' || c == '"') + { return parse_string (); + } if (__isspace (c)) - { - grobble_whitespaces (); - return lexer_next_token_private (); - } + { + grobble_whitespaces (); + return lexer_next_token_private (); + } if (c == '/' && LA (1) == '*') + { + if (replace_comment_by_newline ()) { - if (replace_comment_by_newline ()) - return (token) { .type = TOK_NEWLINE, .data.uid = 0 }; - else - return lexer_next_token_private (); + return (token) + { + .type = TOK_NEWLINE, + .data.uid = 0 + }; } - - if (c == '/' && LA (1) == '/') + else { - replace_comment_by_newline ();; return lexer_next_token_private (); } + } + + if (c == '/' && LA (1) == '/') + { + replace_comment_by_newline ();; + return lexer_next_token_private (); + } switch (c) { @@ -855,7 +1269,7 @@ lexer_next_token_private (void) case '&': IF_LA_IS_OR ('&', TOK_DOUBLE_AND, '=', TOK_AND_EQ, TOK_AND); case '|': IF_LA_IS_OR ('|', TOK_DOUBLE_OR, '=', TOK_OR_EQ, TOK_OR); - case '<': + case '<': switch (LA (1)) { case '<': IF_LA_N_IS ('=', TOK_LSHIFT_EQ, TOK_LSHIFT, 2); @@ -879,18 +1293,25 @@ lexer_next_token_private (void) case '=': if (LA (1) == '=') + { IF_LA_N_IS ('=', TOK_TRIPLE_EQ, TOK_DOUBLE_EQ, 2); + } else + { RETURN_PUNC (TOK_EQ); + } case '!': if (LA (1) == '=') + { IF_LA_N_IS ('=', TOK_NOT_DOUBLE_EQ, TOK_NOT_EQ, 2); + } else + { RETURN_PUNC (TOK_NOT); + } - default: - JERRY_UNREACHABLE (); + default: JERRY_UNREACHABLE (); } parser_fatal (ERR_NON_CHAR); } @@ -900,17 +1321,19 @@ lexer_next_token (void) { #ifdef __TARGET_HOST_x64 if (buffer == buffer_start) + { dump_current_line (); + } #endif /* __TARGET_HOST_x64 */ token tok = lexer_next_token_private (); #ifdef __TARGET_HOST_x64 if (tok.type == TOK_NEWLINE) - { - dump_current_line (); - return tok; - } + { + dump_current_line (); + return tok; + } #endif /* __TARGET_HOST_x64 */ return tok; } @@ -938,13 +1361,15 @@ lexer_init (const char *source, size_t source_size, bool show_opcodes) } void -lexer_run_first_pass( void) +lexer_run_first_pass (void) { token tok = lexer_next_token (); while (tok.type != TOK_EOF) - tok = lexer_next_token (); + { + tok = lexer_next_token (); + } - lexer_rewind(); + lexer_rewind (); } void diff --git a/src/libjsparser/lexer.h b/src/libjsparser/lexer.h index 9cbc6b1ea..9b7f3b62d 100644 --- a/src/libjsparser/lexer.h +++ b/src/libjsparser/lexer.h @@ -62,9 +62,9 @@ typedef uint8_t keyword; /* Type of tokens. */ typedef uint8_t token_type; -#define TOK_EOF 0 // End of file -#define TOK_NAME 1 // Identifier -#define TOK_KEYWORD 2 // Keyword +#define TOK_EOF 0 // End of file +#define TOK_NAME 1 // Identifier +#define TOK_KEYWORD 2 // Keyword #define TOK_INT 3 #define TOK_FLOAT 4 @@ -72,84 +72,84 @@ typedef uint8_t token_type; #define TOK_BOOL 6 #define TOK_NEWLINE 7 #define TOK_STRING 8 -#define TOK_OPEN_BRACE 9 // { +#define TOK_OPEN_BRACE 9 // { -#define TOK_CLOSE_BRACE 10 // } -#define TOK_OPEN_PAREN 11 // ( -#define TOK_CLOSE_PAREN 12 // ) -#define TOK_OPEN_SQUARE 13 // [ -#define TOK_CLOSE_SQUARE 14 // [ +#define TOK_CLOSE_BRACE 10 // } +#define TOK_OPEN_PAREN 11 // ( +#define TOK_CLOSE_PAREN 12 // ) +#define TOK_OPEN_SQUARE 13 // [ +#define TOK_CLOSE_SQUARE 14 // [ -#define TOK_DOT 15 // . -#define TOK_SEMICOLON 16 // ; -#define TOK_COMMA 17 // , -#define TOK_LESS 18 // < -#define TOK_GREATER 19 // > +#define TOK_DOT 15 // . +#define TOK_SEMICOLON 16 // ; +#define TOK_COMMA 17 // , +#define TOK_LESS 18 // < +#define TOK_GREATER 19 // > -#define TOK_LESS_EQ 20 // <= -#define TOK_GREATER_EQ 21 // <= -#define TOK_DOUBLE_EQ 22 // == -#define TOK_NOT_EQ 23 // != -#define TOK_TRIPLE_EQ 24 // === +#define TOK_LESS_EQ 20 // <= +#define TOK_GREATER_EQ 21 // <= +#define TOK_DOUBLE_EQ 22 // == +#define TOK_NOT_EQ 23 // != +#define TOK_TRIPLE_EQ 24 // === -#define TOK_NOT_DOUBLE_EQ 25 // !== -#define TOK_PLUS 26 // + -#define TOK_MINUS 27 // - -#define TOK_MULT 28 // * -#define TOK_MOD 29 // % +#define TOK_NOT_DOUBLE_EQ 25 // !== +#define TOK_PLUS 26 // + +#define TOK_MINUS 27 // - +#define TOK_MULT 28 // * +#define TOK_MOD 29 // % -#define TOK_DOUBLE_PLUS 30 // ++ -#define TOK_DOUBLE_MINUS 31 // -- -#define TOK_LSHIFT 32 // << -#define TOK_RSHIFT 33 // >> -#define TOK_RSHIFT_EX 34 // >>> +#define TOK_DOUBLE_PLUS 30 // ++ +#define TOK_DOUBLE_MINUS 31 // -- +#define TOK_LSHIFT 32 // << +#define TOK_RSHIFT 33 // >> +#define TOK_RSHIFT_EX 34 // >>> -#define TOK_AND 35 // & -#define TOK_OR 36 // | -#define TOK_XOR 37 // ^ -#define TOK_NOT 38 // ! -#define TOK_COMPL 39 // ~ +#define TOK_AND 35 // & +#define TOK_OR 36 // | +#define TOK_XOR 37 // ^ +#define TOK_NOT 38 // ! +#define TOK_COMPL 39 // ~ -#define TOK_DOUBLE_AND 40 // && -#define TOK_DOUBLE_OR 41 // || -#define TOK_QUERY 42 // ? -#define TOK_COLON 43 // : -#define TOK_EQ 44 // = +#define TOK_DOUBLE_AND 40 // && +#define TOK_DOUBLE_OR 41 // || +#define TOK_QUERY 42 // ? +#define TOK_COLON 43 // : +#define TOK_EQ 44 // = -#define TOK_PLUS_EQ 45 // += -#define TOK_MINUS_EQ 46 // -= -#define TOK_MULT_EQ 47 // *= -#define TOK_MOD_EQ 48 // %= -#define TOK_LSHIFT_EQ 49 // <<= +#define TOK_PLUS_EQ 45 // += +#define TOK_MINUS_EQ 46 // -= +#define TOK_MULT_EQ 47 // *= +#define TOK_MOD_EQ 48 // %= +#define TOK_LSHIFT_EQ 49 // <<= -#define TOK_RSHIFT_EQ 50 // >>= -#define TOK_RSHIFT_EX_EQ 51 // >>>= -#define TOK_AND_EQ 52 // &= -#define TOK_OR_EQ 53 // |= -#define TOK_XOR_EQ 54 // ^= +#define TOK_RSHIFT_EQ 50 // >>= +#define TOK_RSHIFT_EX_EQ 51 // >>>= +#define TOK_AND_EQ 52 // &= +#define TOK_OR_EQ 53 // |= +#define TOK_XOR_EQ 54 // ^= -#define TOK_DIV 55 // / -#define TOK_DIV_EQ 56 // /= +#define TOK_DIV 55 // / +#define TOK_DIV_EQ 56 // /= #define TOK_EMPTY 57 /* Represents the contents of a token. */ -typedef struct +typedef struct { token_type type; union - { - keyword kw; - uint8_t uid; - } + { + keyword kw; + uint8_t uid; + } data; } __packed token; -void lexer_init(const char *, size_t, bool); +void lexer_init (const char *, size_t, bool); void lexer_free (void); -void lexer_run_first_pass( void); +void lexer_run_first_pass (void); token lexer_next_token (void); void lexer_save_token (token); void lexer_dump_buffer_state (void); diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index 3dc2907a9..9428f4c2e 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -51,7 +51,7 @@ static opcode_counter_t opcode_counter = 0; static T_IDX temp_name_stack[MAX_OPCODES], temp_name_stack_head = 0, max_temp_name; static uint8_t nestings[MAX_NESTINGS], nestings_head = 0; -static rewritable_opcode rewritable_opcodes[REWRITABLE_OPCODES_COUNT] = +static rewritable_opcode rewritable_opcodes[REWRITABLE_OPCODES_COUNT] = { [REWRITABLE_CONTINUE] = { .size = 0, .head = 0, .oc_stack = NULL }, [REWRITABLE_BREAK] = { .size = 0, .head = 0, .oc_stack = NULL } @@ -88,7 +88,9 @@ static void reset_temp_name (void) { if (max_temp_name < temp_name) + { max_temp_name = temp_name; + } temp_name = min_temp_name; } @@ -115,21 +117,27 @@ must_be_inside_but_not_in (uint8_t inside[], uint8_t insides_count, uint8_t not_ int8_t i; if (nestings_head == 0) + { parser_fatal (ERR_PARSER); + } for (i = (int8_t) (nestings_head - 1); i >= 0; i--) + { + int8_t j; + if (nestings[i] == not_in) { - int8_t j; - if (nestings[i] == not_in) - parser_fatal (ERR_PARSER); - - for (j = 0; j < insides_count; j++) - { - if (nestings[i] == inside[j]) - return; - } + parser_fatal (ERR_PARSER); } + for (j = 0; j < insides_count; j++) + { + if (nestings[i] == inside[j]) + { + return; + } + } + } + parser_fatal (ERR_PARSER); } @@ -137,13 +145,13 @@ static void assert_keyword (keyword kw) { if (tok.type != TOK_KEYWORD || tok.data.kw != kw) - { + { #ifdef __TARGET_HOST_x64 - __printf ("assert_keyword: %d\n", kw); + __printf ("assert_keyword: %d\n", kw); #endif - JERRY_UNREACHABLE (); - } -} + JERRY_UNREACHABLE (); + } +} static bool is_keyword (keyword kw) @@ -152,15 +160,15 @@ is_keyword (keyword kw) } static void -current_token_must_be(token_type tt) +current_token_must_be(token_type tt) { - if (tok.type != tt) - { + if (tok.type != tt) + { #ifdef __TARGET_HOST_x64 - __printf ("current_token_must_be: %d\n", tt); + __printf ("current_token_must_be: %d\n", tt); #endif - parser_fatal (ERR_PARSER); - } + parser_fatal (ERR_PARSER); + } } static void @@ -168,7 +176,9 @@ skip_newlines (void) { tok = lexer_next_token (); while (tok.type == TOK_NEWLINE) + { tok = lexer_next_token (); + } } static void @@ -176,12 +186,12 @@ next_token_must_be (token_type tt) { tok = lexer_next_token (); if (tok.type != tt) - { + { #ifdef __TARGET_HOST_x64 - __printf ("next_token_must_be: %d\n", tt); + __printf ("next_token_must_be: %d\n", tt); #endif - parser_fatal (ERR_PARSER); - } + parser_fatal (ERR_PARSER); + } } static void @@ -189,7 +199,9 @@ token_after_newlines_must_be (token_type tt) { skip_newlines (); if (tok.type != tt) + { parser_fatal (ERR_PARSER); + } } static inline void @@ -197,7 +209,9 @@ token_after_newlines_must_be_keyword (keyword kw) { skip_newlines (); if (!is_keyword (kw)) + { parser_fatal (ERR_PARSER); + } } #if 0 @@ -206,7 +220,9 @@ insert_semicolon (void) { tok = lexer_next_token (); if (tok.type != TOK_NEWLINE && tok.type != TOK_SEMICOLON) + { parser_fatal (ERR_PARSER); + } } #endif @@ -292,24 +308,24 @@ add_to_rewritable_opcodes (rewritable_opcode_type type, opcode_counter_t oc) { rewritable_opcode op = rewritable_opcodes[type]; if (op.oc_stack == NULL) - { - op.size = op.head = 1; - op.oc_stack = (opcode_counter_t *) mem_heap_alloc_block (sizeof (opcode_counter_t), MEM_HEAP_ALLOC_SHORT_TERM); - op.oc_stack[0] = oc; - return; - } + { + op.size = op.head = 1; + op.oc_stack = (opcode_counter_t *) mem_heap_alloc_block (sizeof (opcode_counter_t), MEM_HEAP_ALLOC_SHORT_TERM); + op.oc_stack[0] = oc; + return; + } if (op.head == op.size) - { - opcode_counter_t *temp = (opcode_counter_t *) mem_heap_alloc_block (sizeof (opcode_counter_t) * op.size * 2, - MEM_HEAP_ALLOC_SHORT_TERM); - __memcpy (temp, op.oc_stack, op.size * sizeof (opcode_counter_t)); - op.size = (uint8_t) (op.size * 2); - temp[op.head++] = oc; - mem_heap_free_block ((uint8_t *) op.oc_stack); - op.oc_stack = temp; - return; - } + { + opcode_counter_t *temp = (opcode_counter_t *) mem_heap_alloc_block (sizeof (opcode_counter_t) * op.size * 2, + MEM_HEAP_ALLOC_SHORT_TERM); + __memcpy (temp, op.oc_stack, op.size * sizeof (opcode_counter_t)); + op.size = (uint8_t) (op.size * 2); + temp[op.head++] = oc; + mem_heap_free_block ((uint8_t *) op.oc_stack); + op.oc_stack = temp; + return; + } op.oc_stack[op.head++] = oc; } @@ -321,24 +337,24 @@ rewrite_rewritable_opcodes (rewritable_opcode_type type, opcode_counter_t oc) rewritable_opcode op = rewritable_opcodes[type]; for (i = 0; i < op.head; i++) + { + switch (type) { - switch (type) - { - case REWRITABLE_CONTINUE: - REWRITE_OPCODE_1 (op.oc_stack[i], jmp_up, oc); - break; - case REWRITABLE_BREAK: - REWRITE_OPCODE_1 (op.oc_stack[i], jmp_down, oc); - break; - default: - JERRY_UNREACHABLE (); - } + case REWRITABLE_CONTINUE: + REWRITE_OPCODE_1 (op.oc_stack[i], jmp_up, oc); + break; + case REWRITABLE_BREAK: + REWRITE_OPCODE_1 (op.oc_stack[i], jmp_down, oc); + break; + default: + JERRY_UNREACHABLE (); } + } if (op.oc_stack) - { - mem_heap_free_block ((uint8_t *) op.oc_stack); - } + { + mem_heap_free_block ((uint8_t *) op.oc_stack); + } op.oc_stack = NULL; op.head = op.size = 0; } @@ -347,9 +363,9 @@ static int8_t intrinsic_argument_count (const char *intrinsic) { if (!__strcmp (intrinsic, "assert")) - { - return 1; - } + { + return 1; + } return -1; } @@ -362,10 +378,10 @@ is_intrinsic (T_IDX obj) it is identifier, check for intrinsics. */ uint8_t strings_count = lexer_get_strings (NULL); if (obj < strings_count) - { - const char *string = lexer_get_string_by_id (obj); - return intrinsic_argument_count (string) >= 0; - } + { + const char *string = lexer_get_string_by_id (obj); + return intrinsic_argument_count (string) >= 0; + } return false; } @@ -375,19 +391,19 @@ dump_intrinsic (T_IDX obj, T_IDX args[3]) { uint8_t strings_count = lexer_get_strings (NULL); if (obj < strings_count) + { + const char *string = lexer_get_string_by_id (obj); + if (!__strcmp (string, "assert")) { - const char *string = lexer_get_string_by_id (obj); - if (!__strcmp (string, "assert")) - { - /* Dump opcodes like - is_true_jmp arg, +2 - exitval 1 - */ - DUMP_OPCODE_2 (is_true_jmp, args[0], opcode_counter + 2); - DUMP_OPCODE_1 (exitval, 1); - return; - } + /* Dump opcodes like + is_true_jmp arg, +2 + exitval 1 + */ + DUMP_OPCODE_2 (is_true_jmp, args[0], opcode_counter + 2); + DUMP_OPCODE_1 (exitval, 1); + return; } + } JERRY_UNREACHABLE (); } @@ -399,7 +415,7 @@ dump_intrinsic (T_IDX obj, T_IDX args[3]) ; */ static T_IDX parse_property_name (void) -{ +{ switch (tok.type) { case TOK_NAME: @@ -433,7 +449,7 @@ parse_property_name_and_value (void) /* property_assignment : property_name_and_value | get LT!* property_name LT!* '(' LT!* ')' LT!* '{' LT!* function_body LT!* '}' - | set LT!* property_name LT!* '(' identifier ')' LT!* '{' LT!* function_body LT!* '}' + | set LT!* property_name LT!* '(' identifier ')' LT!* '{' LT!* function_body LT!* '}' ; */ static T_IDX parse_property_assignment (void) @@ -445,55 +461,57 @@ parse_property_assignment (void) lhs = next_temp_name (); if (!__strcmp ("get", lexer_get_string_by_id (tok.data.uid))) - { - NEXT (name, property_name); + { + NEXT (name, property_name); - token_after_newlines_must_be (TOK_OPEN_PAREN); - token_after_newlines_must_be (TOK_CLOSE_PAREN); - token_after_newlines_must_be (TOK_OPEN_BRACE); + token_after_newlines_must_be (TOK_OPEN_PAREN); + token_after_newlines_must_be (TOK_CLOSE_PAREN); + token_after_newlines_must_be (TOK_OPEN_BRACE); - DUMP_OPCODE_2 (prop_get_decl, lhs, name); + DUMP_OPCODE_2 (prop_get_decl, lhs, name); - skip_newlines (); - parse_source_element_list (); + skip_newlines (); + parse_source_element_list (); - token_after_newlines_must_be (TOK_CLOSE_BRACE); - DUMP_VOID_OPCODE (ret); + token_after_newlines_must_be (TOK_CLOSE_BRACE); + DUMP_VOID_OPCODE (ret); - return lhs; - } + return lhs; + } else if (!__strcmp ("set", lexer_get_string_by_id (tok.data.uid))) - { - NEXT (name, property_name); + { + NEXT (name, property_name); - token_after_newlines_must_be (TOK_OPEN_PAREN); - token_after_newlines_must_be (TOK_NAME); - arg = tok.data.uid; - token_after_newlines_must_be (TOK_CLOSE_PAREN); - token_after_newlines_must_be (TOK_OPEN_BRACE); + token_after_newlines_must_be (TOK_OPEN_PAREN); + token_after_newlines_must_be (TOK_NAME); + arg = tok.data.uid; + token_after_newlines_must_be (TOK_CLOSE_PAREN); + token_after_newlines_must_be (TOK_OPEN_BRACE); - DUMP_OPCODE_3 (prop_set_decl, lhs, name, arg); + DUMP_OPCODE_3 (prop_set_decl, lhs, name, arg); - skip_newlines (); - parse_source_element_list (); + skip_newlines (); + parse_source_element_list (); - token_after_newlines_must_be (TOK_CLOSE_BRACE); - DUMP_VOID_OPCODE (ret); + token_after_newlines_must_be (TOK_CLOSE_BRACE); + DUMP_VOID_OPCODE (ret); - return lhs; - } + return lhs; + } else + { return parse_property_name_and_value (); + } } static void dump_varg_3 (T_IDX current_param, T_IDX params[3]) { if (current_param == 3) - { - DUMP_OPCODE_3 (varg_3, params[0], params[1], params[2]); - current_param = 0; - } + { + DUMP_OPCODE_3 (varg_3, params[0], params[1], params[2]); + current_param = 0; + } } static void @@ -504,11 +522,11 @@ dump_varg_end (T_IDX current_param, T_IDX params[3]) case 0: DUMP_OPCODE_1 (varg_1_end, params[0]); break; - + case 1: DUMP_OPCODE_2 (varg_2_end, params[0], params[1]); break; - + case 2: DUMP_OPCODE_3 (varg_3_end, params[0], params[1], params[2]); break; @@ -529,16 +547,16 @@ typedef enum } argument_list_type; -/** Parse list of identifiers, assigment expressions or properties, splitted by comma. +/** Parse list of identifiers, assigment expressions or properties, splitted by comma. For each ALT dumps appropriate bytecode. Uses OBJ during dump if neccesary. Returns temp var if expression has lhs, or 0 otherwise. */ static T_IDX parse_argument_list (argument_list_type alt, T_IDX obj) { token_type open_tt, close_tt; - T_IDX first_opcode_args_count, - lhs = 0, - args[3+1/* +1 for stack protector */], + T_IDX first_opcode_args_count, + lhs = 0, + args[3+1/* +1 for stack protector */], current_arg = 0; switch (alt) @@ -562,9 +580,9 @@ parse_argument_list (argument_list_type alt, T_IDX obj) close_tt = TOK_CLOSE_PAREN; first_opcode_args_count = 1; if (is_intrinsic (obj)) - { - break; - } + { + break; + } lhs = next_temp_name (); break; @@ -590,197 +608,203 @@ parse_argument_list (argument_list_type alt, T_IDX obj) skip_newlines (); if (tok.type != close_tt) + { + bool is_first_opcode = true; + while (true) { - bool is_first_opcode = true; - while (true) + if (is_first_opcode) + { + if (current_arg == first_opcode_args_count) { - if (is_first_opcode) - { - if (current_arg == first_opcode_args_count) - { - switch (alt) - { - case AL_FUNC_DECL: - DUMP_OPCODE_3 (func_decl_n, obj, args[0], args[1]); - break; - - case AL_FUNC_EXPR: - DUMP_OPCODE_3 (func_expr_n, lhs, obj, args[0]); - break; - - case AL_ARRAY_LIT: - DUMP_OPCODE_3 (array_n, lhs, args[0], args[1]); - break; - - case AL_OBJECT_LIT: - DUMP_OPCODE_3 (obj_n, lhs, args[0], args[1]); - break; - - case AL_CONSTRUCT_EXPR: - DUMP_OPCODE_3 (construct_n, lhs, obj, args[0]); - break; - - case AL_CALL_EXPR: - if (is_intrinsic (obj)) - { - parser_fatal (ERR_PARSER); - } - DUMP_OPCODE_3 (call_n, lhs, obj, args[0]); - break; - - default: - JERRY_UNREACHABLE (); - } - current_arg = 0; - is_first_opcode = false; - } - } - else - dump_varg_3 (current_arg, args); - switch (alt) { case AL_FUNC_DECL: - current_token_must_be (TOK_NAME); - args[current_arg] = tok.data.uid; + DUMP_OPCODE_3 (func_decl_n, obj, args[0], args[1]); break; case AL_FUNC_EXPR: + DUMP_OPCODE_3 (func_expr_n, lhs, obj, args[0]); + break; + case AL_ARRAY_LIT: - case AL_CONSTRUCT_EXPR: - case AL_CALL_EXPR: - args[current_arg] = parse_assignment_expression (); + DUMP_OPCODE_3 (array_n, lhs, args[0], args[1]); break; case AL_OBJECT_LIT: - args[current_arg] = parse_property_assignment (); + DUMP_OPCODE_3 (obj_n, lhs, args[0], args[1]); + break; + + case AL_CONSTRUCT_EXPR: + DUMP_OPCODE_3 (construct_n, lhs, obj, args[0]); + break; + + case AL_CALL_EXPR: + if (is_intrinsic (obj)) + { + parser_fatal (ERR_PARSER); + } + DUMP_OPCODE_3 (call_n, lhs, obj, args[0]); break; default: JERRY_UNREACHABLE (); } - - skip_newlines (); - if (tok.type != TOK_COMMA) - { - current_token_must_be (close_tt); - break; - } - - skip_newlines (); - current_arg++; - } - - if (is_first_opcode) - { - if (current_arg == 0) - { - switch (alt) - { - case AL_FUNC_DECL: - DUMP_OPCODE_2 (func_decl_1, obj, args[0]); - break; - - case AL_FUNC_EXPR: - DUMP_OPCODE_3 (func_expr_1, lhs, obj, args[0]); - break; - - case AL_ARRAY_LIT: - DUMP_OPCODE_2 (array_1, lhs, args[0]); - break; - - case AL_OBJECT_LIT: - DUMP_OPCODE_2 (obj_1, lhs, args[0]); - break; - - case AL_CONSTRUCT_EXPR: - DUMP_OPCODE_3 (construct_1, lhs, obj, args[0]); - break; - - case AL_CALL_EXPR: - if (is_intrinsic (obj)) - { - dump_intrinsic (obj, args); - } - else - { - DUMP_OPCODE_3 (call_1, lhs, obj, args[0]); - } - break; - - default: - JERRY_UNREACHABLE (); - } - } - else if (current_arg == 1) - { - switch (alt) - { - case AL_FUNC_DECL: - DUMP_OPCODE_3 (func_decl_2, obj, args[0], args[1]); - break; - - case AL_ARRAY_LIT: - DUMP_OPCODE_3 (array_2, lhs, args[0], args[1]); - break; - - case AL_OBJECT_LIT: - DUMP_OPCODE_3 (obj_2, lhs, args[0], args[1]); - break; - - default: - JERRY_UNREACHABLE (); - } - } - else - JERRY_UNREACHABLE (); + current_arg = 0; + is_first_opcode = false; } + } else - dump_varg_end (current_arg, args); - } - else - { + { + dump_varg_3 (current_arg, args); + } + switch (alt) { case AL_FUNC_DECL: - DUMP_OPCODE_1 (func_decl_0, obj); + current_token_must_be (TOK_NAME); + args[current_arg] = tok.data.uid; break; case AL_FUNC_EXPR: - DUMP_OPCODE_2 (func_expr_0, lhs, obj); - break; - case AL_ARRAY_LIT: - DUMP_OPCODE_1 (array_0, lhs); + case AL_CONSTRUCT_EXPR: + case AL_CALL_EXPR: + args[current_arg] = parse_assignment_expression (); break; case AL_OBJECT_LIT: - DUMP_OPCODE_1 (obj_0, lhs); - break; - - case AL_CONSTRUCT_EXPR: - DUMP_OPCODE_2 (construct_0, lhs, obj); - break; - - case AL_CALL_EXPR: - DUMP_OPCODE_2 (call_0, lhs, obj); + args[current_arg] = parse_property_assignment (); break; default: JERRY_UNREACHABLE (); } + + skip_newlines (); + if (tok.type != TOK_COMMA) + { + current_token_must_be (close_tt); + break; + } + + skip_newlines (); + current_arg++; } + if (is_first_opcode) + { + if (current_arg == 0) + { + switch (alt) + { + case AL_FUNC_DECL: + DUMP_OPCODE_2 (func_decl_1, obj, args[0]); + break; + + case AL_FUNC_EXPR: + DUMP_OPCODE_3 (func_expr_1, lhs, obj, args[0]); + break; + + case AL_ARRAY_LIT: + DUMP_OPCODE_2 (array_1, lhs, args[0]); + break; + + case AL_OBJECT_LIT: + DUMP_OPCODE_2 (obj_1, lhs, args[0]); + break; + + case AL_CONSTRUCT_EXPR: + DUMP_OPCODE_3 (construct_1, lhs, obj, args[0]); + break; + + case AL_CALL_EXPR: + if (is_intrinsic (obj)) + { + dump_intrinsic (obj, args); + } + else + { + DUMP_OPCODE_3 (call_1, lhs, obj, args[0]); + } + break; + + default: + JERRY_UNREACHABLE (); + } + } + else if (current_arg == 1) + { + switch (alt) + { + case AL_FUNC_DECL: + DUMP_OPCODE_3 (func_decl_2, obj, args[0], args[1]); + break; + + case AL_ARRAY_LIT: + DUMP_OPCODE_3 (array_2, lhs, args[0], args[1]); + break; + + case AL_OBJECT_LIT: + DUMP_OPCODE_3 (obj_2, lhs, args[0], args[1]); + break; + + default: + JERRY_UNREACHABLE (); + } + } + else + { + JERRY_UNREACHABLE (); + } + } + else + { + dump_varg_end (current_arg, args); + } + } + else + { + switch (alt) + { + case AL_FUNC_DECL: + DUMP_OPCODE_1 (func_decl_0, obj); + break; + + case AL_FUNC_EXPR: + DUMP_OPCODE_2 (func_expr_0, lhs, obj); + break; + + case AL_ARRAY_LIT: + DUMP_OPCODE_1 (array_0, lhs); + break; + + case AL_OBJECT_LIT: + DUMP_OPCODE_1 (obj_0, lhs); + break; + + case AL_CONSTRUCT_EXPR: + DUMP_OPCODE_2 (construct_0, lhs, obj); + break; + + case AL_CALL_EXPR: + DUMP_OPCODE_2 (call_0, lhs, obj); + break; + + default: + JERRY_UNREACHABLE (); + } + } + return lhs; } /* function_declaration - : 'function' LT!* Identifier LT!* - '(' (LT!* Identifier (LT!* ',' LT!* Identifier)* ) ? LT!* ')' LT!* function_body - ; + : 'function' LT!* Identifier LT!* + '(' (LT!* Identifier (LT!* ',' LT!* Identifier)* ) ? LT!* ')' LT!* function_body + ; function_body - : '{' LT!* sourceElements LT!* '}' */ + : '{' LT!* sourceElements LT!* '}' */ static void parse_function_declaration (void) { @@ -813,8 +837,8 @@ parse_function_declaration (void) } /* function_expression - : 'function' LT!* Identifier? LT!* '(' formal_parameter_list? LT!* ')' LT!* function_body - ; */ + : 'function' LT!* Identifier? LT!* '(' formal_parameter_list? LT!* ')' LT!* function_body + ; */ static T_IDX parse_function_expression (void) { @@ -825,15 +849,17 @@ parse_function_expression (void) skip_newlines (); if (tok.type == TOK_NAME) + { name = tok.data.uid; + } else - { - lexer_save_token (tok); - name = next_temp_name (); - } + { + lexer_save_token (tok); + name = next_temp_name (); + } skip_newlines (); - lhs = parse_argument_list (AL_FUNC_EXPR, name); + lhs = parse_argument_list (AL_FUNC_EXPR, name); jmp_oc = opcode_counter; DUMP_OPCODE_1 (jmp_down, INVALID_VALUE); @@ -854,7 +880,7 @@ parse_function_expression (void) } /* array_literal - : '[' LT!* assignment_expression? (LT!* ',' (LT!* assignment_expression)?)* LT!* ']' LT!* + : '[' LT!* assignment_expression? (LT!* ',' (LT!* assignment_expression)?)* LT!* ']' LT!* ; */ static T_IDX parse_array_literal (void) @@ -865,7 +891,7 @@ parse_array_literal (void) /* object_literal : '{' LT!* property_assignment (LT!* ',' LT!* property_assignment)* LT!* '}' ; */ -static T_IDX +static T_IDX parse_object_literal (void) { return parse_argument_list (AL_OBJECT_LIT, 0); @@ -885,8 +911,8 @@ parse_literal (void) case TOK_BOOL: lhs = next_temp_name (); - DUMP_OPCODE_3 (assignment, lhs, OPCODE_ARG_TYPE_SIMPLE, - tok.data.uid ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); + DUMP_OPCODE_3 (assignment, lhs, OPCODE_ARG_TYPE_SIMPLE, + tok.data.uid ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); return lhs; case TOK_INT: @@ -918,37 +944,45 @@ parse_primary_expression (void) T_IDX lhs; if (is_keyword (KW_THIS)) + { + lhs = next_temp_name (); + DUMP_OPCODE_1 (this, lhs); + return lhs; + } + else if (tok.type == TOK_NAME) + { + return tok.data.uid; + } + else if (tok.type == TOK_NULL || tok.type == TOK_BOOL + || tok.type == TOK_INT || tok.type == TOK_STRING) + { + return parse_literal (); + } + else if (tok.type == TOK_OPEN_SQUARE) + { + return parse_array_literal (); + } + else if (tok.type == TOK_OPEN_BRACE) + { + return parse_object_literal (); + } + else if (tok.type == TOK_OPEN_PAREN) + { + skip_newlines (); + if (tok.type != TOK_CLOSE_PAREN) { - lhs = next_temp_name (); - DUMP_OPCODE_1 (this, lhs); + lhs = parse_expression (); + token_after_newlines_must_be (TOK_CLOSE_PAREN); return lhs; } - else if (tok.type == TOK_NAME) - return tok.data.uid; - else if (tok.type == TOK_NULL || tok.type == TOK_BOOL - || tok.type == TOK_INT || tok.type == TOK_STRING) - return parse_literal (); - else if (tok.type == TOK_OPEN_SQUARE) - return parse_array_literal (); - else if (tok.type == TOK_OPEN_BRACE) - return parse_object_literal (); - else if (tok.type == TOK_OPEN_PAREN) - { - skip_newlines (); - if (tok.type != TOK_CLOSE_PAREN) - { - lhs = parse_expression (); - token_after_newlines_must_be (TOK_CLOSE_PAREN); - return lhs; - } - } + } JERRY_UNREACHABLE (); } /* member_expression - : (primary_expression | function_expression | 'new' LT!* member_expression (LT!* '(' LT!* arguments? LT!* ')') + : (primary_expression | function_expression | 'new' LT!* member_expression (LT!* '(' LT!* arguments? LT!* ')') (LT!* member_expression_suffix)* - ; + ; arguments : assignment_expression (LT!* ',' LT!* assignment_expression)*)? @@ -958,11 +992,11 @@ parse_primary_expression (void) : index_suffix | property_reference_suffix ; - + index_suffix : '[' LT!* expression LT!* ']' - ; - + ; + property_reference_suffix : '.' LT!* Identifier ; */ @@ -971,46 +1005,50 @@ parse_member_expression (void) { T_IDX lhs, obj, prop; if (is_keyword (KW_FUNCTION)) - { - obj = parse_function_expression (); - } + { + obj = parse_function_expression (); + } else if (is_keyword (KW_NEW)) - { - T_IDX member; + { + T_IDX member; - NEXT (member, member_expression); + NEXT (member, member_expression); - obj = parse_argument_list (AL_CONSTRUCT_EXPR, member); - } + obj = parse_argument_list (AL_CONSTRUCT_EXPR, member); + } else - { - obj = parse_primary_expression (); - } + { + obj = parse_primary_expression (); + } skip_newlines (); while (tok.type == TOK_OPEN_SQUARE || tok.type == TOK_DOT) + { + lhs = next_temp_name (); + + if (tok.type == TOK_OPEN_SQUARE) { - lhs = next_temp_name (); - - if (tok.type == TOK_OPEN_SQUARE) - { - NEXT (prop, expression); - next_token_must_be (TOK_CLOSE_SQUARE); - } - else if (tok.type == TOK_DOT) - { - skip_newlines (); - if (tok.type != TOK_NAME) - parser_fatal (ERR_PARSER); - prop = tok.data.uid; - } - else - JERRY_UNREACHABLE (); - - DUMP_OPCODE_3 (prop_access, lhs, obj, prop); - obj = lhs; - skip_newlines (); + NEXT (prop, expression); + next_token_must_be (TOK_CLOSE_SQUARE); } + else if (tok.type == TOK_DOT) + { + skip_newlines (); + if (tok.type != TOK_NAME) + { + parser_fatal (ERR_PARSER); + } + prop = tok.data.uid; + } + else + { + JERRY_UNREACHABLE (); + } + + DUMP_OPCODE_3 (prop_access, lhs, obj, prop); + obj = lhs; + skip_newlines (); + } lexer_save_token (tok); @@ -1025,7 +1063,7 @@ parse_member_expression (void) : arguments | index_suffix | property_reference_suffix - ; + ; arguments : '(' LT!* assignment_expression LT!* ( ',' LT!* assignment_expression * LT!* )* ')' @@ -1039,47 +1077,47 @@ parse_call_expression (void) skip_newlines (); if (tok.type != TOK_OPEN_PAREN) - { - lexer_save_token (tok); - return obj; - } + { + lexer_save_token (tok); + return obj; + } lhs = parse_argument_list (AL_CALL_EXPR, obj); obj = lhs; skip_newlines (); - while (tok.type == TOK_OPEN_PAREN || tok.type == TOK_OPEN_SQUARE + while (tok.type == TOK_OPEN_PAREN || tok.type == TOK_OPEN_SQUARE || tok.type == TOK_DOT) + { + switch (tok.type) { - switch (tok.type) - { - case TOK_OPEN_PAREN: - lhs = parse_argument_list (AL_CALL_EXPR, obj); - skip_newlines (); - break; + case TOK_OPEN_PAREN: + lhs = parse_argument_list (AL_CALL_EXPR, obj); + skip_newlines (); + break; - case TOK_OPEN_SQUARE: - NEXT (prop, expression); - next_token_must_be (TOK_CLOSE_SQUARE); + case TOK_OPEN_SQUARE: + NEXT (prop, expression); + next_token_must_be (TOK_CLOSE_SQUARE); - DUMP_OPCODE_3 (prop_access, lhs, obj, prop); - obj = lhs; - skip_newlines (); - break; + DUMP_OPCODE_3 (prop_access, lhs, obj, prop); + obj = lhs; + skip_newlines (); + break; - case TOK_DOT: - token_after_newlines_must_be (TOK_NAME); - prop = tok.data.uid; + case TOK_DOT: + token_after_newlines_must_be (TOK_NAME); + prop = tok.data.uid; - DUMP_OPCODE_3 (prop_access, lhs, obj, prop); - obj = lhs; - skip_newlines (); - break; + DUMP_OPCODE_3 (prop_access, lhs, obj, prop); + obj = lhs; + skip_newlines (); + break; - default: - JERRY_UNREACHABLE (); - } + default: + JERRY_UNREACHABLE (); } + } lexer_save_token (tok); return obj; @@ -1105,17 +1143,19 @@ parse_postfix_expression (void) tok = lexer_next_token (); if (tok.type == TOK_DOUBLE_PLUS) - { - lhs = next_temp_name (); - DUMP_OPCODE_2 (post_incr, lhs, expr); - } + { + lhs = next_temp_name (); + DUMP_OPCODE_2 (post_incr, lhs, expr); + } else if (tok.type == TOK_DOUBLE_MINUS) - { - lhs = next_temp_name (); - DUMP_OPCODE_2 (post_decr, lhs, expr); - } + { + lhs = next_temp_name (); + DUMP_OPCODE_2 (post_decr, lhs, expr); + } else + { lexer_save_token (tok); + } return expr; } @@ -1168,22 +1208,24 @@ parse_unary_expression (void) return lhs; case TOK_KEYWORD: - if (is_keyword (KW_DELETE)) - { - lhs = next_temp_name (); - NEXT (expr, unary_expression); - DUMP_OPCODE_2 (delete, lhs, expr); - return lhs; - } - if (is_keyword (KW_VOID)) + if (is_keyword (KW_DELETE)) + { + lhs = next_temp_name (); + NEXT (expr, unary_expression); + DUMP_OPCODE_2 (delete, lhs, expr); + return lhs; + } + if (is_keyword (KW_VOID)) + { JERRY_UNIMPLEMENTED (); + } if (is_keyword (KW_TYPEOF)) - { - lhs = next_temp_name (); - NEXT (expr, unary_expression); - DUMP_OPCODE_2 (typeof, lhs, expr); - return lhs; - } + { + lhs = next_temp_name (); + NEXT (expr, unary_expression); + DUMP_OPCODE_2 (typeof, lhs, expr); + return lhs; + } /* FALLTHRU. */ default: @@ -1210,26 +1252,29 @@ parse_multiplicative_expression (void) skip_newlines (); while (true) + { + switch (tok.type) { - switch (tok.type) - { - case TOK_MULT: DUMP_OF (multiplication, unary_expression) - case TOK_DIV: DUMP_OF (division, unary_expression) - case TOK_MOD: DUMP_OF (remainder, unary_expression) - - default: - lexer_save_token (tok); - return expr1; - } + case TOK_MULT: + DUMP_OF (multiplication, unary_expression) + case TOK_DIV: + DUMP_OF (division, unary_expression) + case TOK_MOD: + DUMP_OF (remainder, unary_expression) - skip_newlines (); + default: + lexer_save_token (tok); + return expr1; } + + skip_newlines (); + } } /* additive_expression : multiplicative_expression (LT!* ('+' | '-') LT!* multiplicative_expression)* ; */ -static T_IDX +static T_IDX parse_additive_expression (void) { T_IDX lhs, expr1, expr2; @@ -1238,19 +1283,21 @@ parse_additive_expression (void) skip_newlines (); while (true) + { + switch (tok.type) { - switch (tok.type) - { - case TOK_PLUS: DUMP_OF (addition, multiplicative_expression); - case TOK_MINUS: DUMP_OF (substraction, multiplicative_expression); - - default: - lexer_save_token (tok); - return expr1; - } + case TOK_PLUS: + DUMP_OF (addition, multiplicative_expression); + case TOK_MINUS: + DUMP_OF (substraction, multiplicative_expression); - skip_newlines (); + default: + lexer_save_token (tok); + return expr1; } + + skip_newlines (); + } } /* shift_expression @@ -1265,20 +1312,23 @@ parse_shift_expression (void) skip_newlines (); while (true) + { + switch (tok.type) { - switch (tok.type) - { - case TOK_LSHIFT: DUMP_OF (b_shift_left, additive_expression) - case TOK_RSHIFT: DUMP_OF (b_shift_right, additive_expression) - case TOK_RSHIFT_EX: DUMP_OF (b_shift_uright, additive_expression) - - default: - lexer_save_token (tok); - return expr1; - } + case TOK_LSHIFT: + DUMP_OF (b_shift_left, additive_expression) + case TOK_RSHIFT: + DUMP_OF (b_shift_right, additive_expression) + case TOK_RSHIFT_EX: + DUMP_OF (b_shift_uright, additive_expression) - skip_newlines (); + default: + lexer_save_token (tok); + return expr1; } + + skip_newlines (); + } } /* relational_expression @@ -1293,31 +1343,35 @@ parse_relational_expression (void) skip_newlines (); while (true) + { + switch (tok.type) { - switch (tok.type) - { - case TOK_LESS: DUMP_OF (less_than, shift_expression) - case TOK_GREATER: DUMP_OF (greater_than, shift_expression) - case TOK_LESS_EQ: DUMP_OF (less_or_equal_than, shift_expression) - case TOK_GREATER_EQ: DUMP_OF (greater_or_equal_than, shift_expression) - case TOK_KEYWORD: - if (is_keyword (KW_INSTANCEOF)) - { - DUMP_OF (instanceof, shift_expression) - } - else if (is_keyword (KW_IN)) - { - DUMP_OF (in, shift_expression) - } - // FALLTHRU - - default: - lexer_save_token (tok); - return expr1; - } + case TOK_LESS: + DUMP_OF (less_than, shift_expression) + case TOK_GREATER: + DUMP_OF (greater_than, shift_expression) + case TOK_LESS_EQ: + DUMP_OF (less_or_equal_than, shift_expression) + case TOK_GREATER_EQ: + DUMP_OF (greater_or_equal_than, shift_expression) + case TOK_KEYWORD: + if (is_keyword (KW_INSTANCEOF)) + { + DUMP_OF (instanceof, shift_expression) + } + else if (is_keyword (KW_IN)) + { + DUMP_OF (in, shift_expression) + } + // FALLTHRU - skip_newlines (); + default: + lexer_save_token (tok); + return expr1; } + + skip_newlines (); + } } /* equality_expression @@ -1332,21 +1386,25 @@ parse_equality_expression (void) skip_newlines (); while (true) + { + switch (tok.type) { - switch (tok.type) - { - case TOK_DOUBLE_EQ: DUMP_OF (equal_value, relational_expression) - case TOK_NOT_EQ: DUMP_OF (not_equal_value, relational_expression) - case TOK_TRIPLE_EQ: DUMP_OF (equal_value_type, relational_expression) - case TOK_NOT_DOUBLE_EQ: DUMP_OF (not_equal_value_type, relational_expression) + case TOK_DOUBLE_EQ: + DUMP_OF (equal_value, relational_expression) + case TOK_NOT_EQ: + DUMP_OF (not_equal_value, relational_expression) + case TOK_TRIPLE_EQ: + DUMP_OF (equal_value_type, relational_expression) + case TOK_NOT_DOUBLE_EQ: + DUMP_OF (not_equal_value_type, relational_expression) - default: - lexer_save_token (tok); - return expr1; - } - - skip_newlines (); + default: + lexer_save_token (tok); + return expr1; } + + skip_newlines (); + } } #define PARSE_OF(FUNC, EXPR, TOK_TYPE, GETOP) \ @@ -1400,40 +1458,40 @@ parse_conditional_expression (bool *was_conditional) skip_newlines (); if (tok.type == TOK_QUERY) - { - T_IDX lhs, res = next_temp_name (); - opcode_counter_t jmp_oc; + { + T_IDX lhs, res = next_temp_name (); + opcode_counter_t jmp_oc; - DUMP_OPCODE_2 (is_true_jmp, expr, opcode_counter + 2); - jmp_oc = opcode_counter; - DUMP_OPCODE_1 (jmp_down, INVALID_VALUE); + DUMP_OPCODE_2 (is_true_jmp, expr, opcode_counter + 2); + jmp_oc = opcode_counter; + DUMP_OPCODE_1 (jmp_down, INVALID_VALUE); - NEXT (lhs, assignment_expression); - DUMP_OPCODE_3 (assignment, res, OPCODE_ARG_TYPE_VARIABLE, lhs); - token_after_newlines_must_be (TOK_COLON); + NEXT (lhs, assignment_expression); + DUMP_OPCODE_3 (assignment, res, OPCODE_ARG_TYPE_VARIABLE, lhs); + token_after_newlines_must_be (TOK_COLON); - REWRITE_OPCODE_1 (jmp_oc, jmp_down, opcode_counter - jmp_oc); - jmp_oc = opcode_counter; - DUMP_OPCODE_1 (jmp_down, INVALID_VALUE); + REWRITE_OPCODE_1 (jmp_oc, jmp_down, opcode_counter - jmp_oc); + jmp_oc = opcode_counter; + DUMP_OPCODE_1 (jmp_down, INVALID_VALUE); - NEXT (lhs, assignment_expression); - DUMP_OPCODE_3 (assignment, res, OPCODE_ARG_TYPE_VARIABLE, lhs); - REWRITE_OPCODE_1 (jmp_oc, jmp_down, opcode_counter - jmp_oc); + NEXT (lhs, assignment_expression); + DUMP_OPCODE_3 (assignment, res, OPCODE_ARG_TYPE_VARIABLE, lhs); + REWRITE_OPCODE_1 (jmp_oc, jmp_down, opcode_counter - jmp_oc); - *was_conditional = true; - return res; - } + *was_conditional = true; + return res; + } else - { - lexer_save_token (tok); - return expr; - } + { + lexer_save_token (tok); + return expr; + } } /* assignment_expression : conditional_expression | left_hand_side_expression LT!* assignment_operator LT!* assignment_expression - ; */ + ; */ static T_IDX parse_assignment_expression (void) { @@ -1442,75 +1500,75 @@ parse_assignment_expression (void) lhs = parse_conditional_expression (&was_conditional); if (was_conditional) - { - return lhs; - } + { + return lhs; + } skip_newlines (); switch (tok.type) - { - case TOK_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (assignment, lhs, OPCODE_ARG_TYPE_VARIABLE, rhs); - break; + { + case TOK_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (assignment, lhs, OPCODE_ARG_TYPE_VARIABLE, rhs); + break; - case TOK_MULT_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (multiplication, lhs, lhs, rhs); - break; + case TOK_MULT_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (multiplication, lhs, lhs, rhs); + break; - case TOK_DIV_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (division, lhs, lhs, rhs); - break; - - case TOK_MOD_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (remainder, lhs, lhs, rhs); - break; - - case TOK_PLUS_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (addition, lhs, lhs, rhs); - break; - - case TOK_MINUS_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (substraction, lhs, lhs, rhs); - break; - - case TOK_LSHIFT_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (b_shift_left, lhs, lhs, rhs); - break; - - case TOK_RSHIFT_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (b_shift_right, lhs, lhs, rhs); - break; - - case TOK_RSHIFT_EX_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (b_shift_uright, lhs, lhs, rhs); - break; - - case TOK_AND_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (b_and, lhs, lhs, rhs); - break; - - case TOK_XOR_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (b_xor, lhs, lhs, rhs); - break; - - case TOK_OR_EQ: - NEXT (rhs, assignment_expression); - DUMP_OPCODE_3 (b_or, lhs, lhs, rhs); - break; - - default: - lexer_save_token (tok); + case TOK_DIV_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (division, lhs, lhs, rhs); + break; + + case TOK_MOD_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (remainder, lhs, lhs, rhs); + break; + + case TOK_PLUS_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (addition, lhs, lhs, rhs); + break; + + case TOK_MINUS_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (substraction, lhs, lhs, rhs); + break; + + case TOK_LSHIFT_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (b_shift_left, lhs, lhs, rhs); + break; + + case TOK_RSHIFT_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (b_shift_right, lhs, lhs, rhs); + break; + + case TOK_RSHIFT_EX_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (b_shift_uright, lhs, lhs, rhs); + break; + + case TOK_AND_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (b_and, lhs, lhs, rhs); + break; + + case TOK_XOR_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (b_xor, lhs, lhs, rhs); + break; + + case TOK_OR_EQ: + NEXT (rhs, assignment_expression); + DUMP_OPCODE_3 (b_or, lhs, lhs, rhs); + break; + + default: + lexer_save_token (tok); } return lhs; @@ -1526,24 +1584,26 @@ parse_expression (void) T_IDX expr = parse_assignment_expression (); while (true) + { + skip_newlines (); + if (tok.type == TOK_COMMA) { - skip_newlines (); - if (tok.type == TOK_COMMA) - NEXT (expr, assignment_expression); - else - { - lexer_save_token (tok); - return expr; - } + NEXT (expr, assignment_expression); } + else + { + lexer_save_token (tok); + return expr; + } + } } /* variable_declaration - : Identifier LT!* initialiser? - ; + : Identifier LT!* initialiser? + ; initialiser - : '=' LT!* assignment_expression - ; */ + : '=' LT!* assignment_expression + ; */ static void parse_variable_declaration (void) { @@ -1555,42 +1615,46 @@ parse_variable_declaration (void) skip_newlines (); if (tok.type == TOK_EQ) - { - NEXT (expr, assignment_expression); - DUMP_OPCODE_3 (assignment, name, OPCODE_ARG_TYPE_VARIABLE, expr); - } + { + NEXT (expr, assignment_expression); + DUMP_OPCODE_3 (assignment, name, OPCODE_ARG_TYPE_VARIABLE, expr); + } else + { lexer_save_token (tok); + } } /* variable_declaration_list - : variable_declaration - (LT!* ',' LT!* variable_declaration)* - ; */ + : variable_declaration + (LT!* ',' LT!* variable_declaration)* + ; */ static void parse_variable_declaration_list (bool *several_decls) { while (true) + { + parse_variable_declaration (); + + skip_newlines (); + if (tok.type != TOK_COMMA) { - parse_variable_declaration (); - - skip_newlines (); - if (tok.type != TOK_COMMA) - { - lexer_save_token (tok); - return; - } - - skip_newlines (); - if (several_decls) - *several_decls = true; + lexer_save_token (tok); + return; } + + skip_newlines (); + if (several_decls) + { + *several_decls = true; + } + } } /* for_statement - : 'for' LT!* '(' (LT!* for_statement_initialiser_part)? LT!* ';' - (LT!* expression)? LT!* ';' (LT!* expression)? LT!* ')' LT!* statement - ; + : 'for' LT!* '(' (LT!* for_statement_initialiser_part)? LT!* ';' + (LT!* expression)? LT!* ';' (LT!* expression)? LT!* ')' LT!* statement + ; for_statement_initialiser_part : expression @@ -1598,9 +1662,9 @@ parse_variable_declaration_list (bool *several_decls) ; for_in_statement - : 'for' LT!* '(' LT!* for_in_statement_initialiser_part LT!* 'in' - LT!* expression LT!* ')' LT!* statement - ; + : 'for' LT!* '(' LT!* for_in_statement_initialiser_part LT!* 'in' + LT!* expression LT!* ')' LT!* statement + ; for_in_statement_initialiser_part : left_hand_side_expression @@ -1618,53 +1682,67 @@ parse_for_or_for_in_statement (void) skip_newlines (); if (tok.type == TOK_SEMICOLON) + { goto plain_for; + } /* Both for_statement_initialiser_part and for_in_statement_initialiser_part contains 'var'. Check it first. */ if (is_keyword (KW_VAR)) + { + bool several_decls = false; + skip_newlines (); + parse_variable_declaration_list (&several_decls); + if (several_decls) { - bool several_decls = false; - skip_newlines (); - parse_variable_declaration_list (&several_decls); - if (several_decls) - { - token_after_newlines_must_be (TOK_SEMICOLON); - goto plain_for; - } - else - { - skip_newlines (); - if (tok.type == TOK_SEMICOLON) - goto plain_for; - else if (is_keyword (KW_IN)) - goto for_in; - else - parser_fatal (ERR_PARSER); - } + token_after_newlines_must_be (TOK_SEMICOLON); + goto plain_for; } + else + { + skip_newlines (); + if (tok.type == TOK_SEMICOLON) + { + goto plain_for; + } + else if (is_keyword (KW_IN)) + { + goto for_in; + } + else + { + parser_fatal (ERR_PARSER); + } + } + } /* expression contains left_hand_side_expression. */ parse_expression (); skip_newlines (); if (tok.type == TOK_SEMICOLON) + { goto plain_for; + } else if (is_keyword (KW_IN)) + { goto for_in; - else + } + else + { parser_fatal (ERR_PARSER); + } JERRY_UNREACHABLE (); plain_for: - /* Represent loop like + /* Represent loop like for (i = 0; i < 10; i++) { body; } as - + 11 i = #0; cond_oc: 12 tmp1 = #10; @@ -1687,12 +1765,14 @@ plain_for: cond_oc = opcode_counter; skip_newlines (); if (tok.type != TOK_SEMICOLON) - { - stop = parse_assignment_expression (); - next_token_must_be (TOK_SEMICOLON); - } + { + stop = parse_assignment_expression (); + next_token_must_be (TOK_SEMICOLON); + } else + { stop = integer_one (); + } end_oc = opcode_counter; DUMP_OPCODE_2 (is_false_jmp, stop, INVALID_VALUE); @@ -1703,10 +1783,10 @@ plain_for: step_oc = opcode_counter; skip_newlines (); if (tok.type != TOK_CLOSE_PAREN) - { - parse_assignment_expression (); - next_token_must_be (TOK_CLOSE_PAREN); - } + { + parse_assignment_expression (); + next_token_must_be (TOK_CLOSE_PAREN); + } DUMP_OPCODE_1 (jmp_up, opcode_counter - cond_oc); REWRITE_OPCODE_1 (body_oc, jmp_down, opcode_counter - body_oc); @@ -1744,20 +1824,20 @@ static void parse_statement_list (void) { while (true) - { - parse_statement (); + { + parse_statement (); + skip_newlines (); + while (tok.type == TOK_SEMICOLON) + { skip_newlines (); - while (tok.type == TOK_SEMICOLON) - { - skip_newlines (); - } - if (tok.type == TOK_CLOSE_BRACE) - { - lexer_save_token (tok); - return; - } } + if (tok.type == TOK_CLOSE_BRACE) + { + lexer_save_token (tok); + return; + } + } } /* if_statement @@ -1781,12 +1861,14 @@ parse_if_statement (void) skip_newlines (); if (is_keyword (KW_ELSE)) - { - skip_newlines (); - parse_statement (); - } + { + skip_newlines (); + parse_statement (); + } else + { lexer_save_token (tok); + } } /* do_while_statement @@ -1853,7 +1935,7 @@ parse_with_statement (void) assert_keyword (KW_WITH); expr = parse_expression_inside_parens (); - DUMP_OPCODE_1 (with, expr); + DUMP_OPCODE_1 (with, expr); skip_newlines (); parse_statement (); @@ -1877,7 +1959,7 @@ parse_switch_statement (void) catch_clause : 'catch' LT!* '(' LT!* Identifier LT!* ')' LT!* '{' LT!* statement_list LT!* '}' ; - + finally_clause : 'finally' LT!* '{' LT!* statement_list LT!* '}' ;*/ @@ -1888,64 +1970,64 @@ parse_try_statement (void) } /* statement - : statement_block - | variable_statement - | empty_statement - | if_statement - | iteration_statement - | continue_statement - | break_statement - | return_statement - | with_statement - | labelled_statement - | switch_statement - | throw_statement - | try_statement - | expression_statement - ; + : statement_block + | variable_statement + | empty_statement + | if_statement + | iteration_statement + | continue_statement + | break_statement + | return_statement + | with_statement + | labelled_statement + | switch_statement + | throw_statement + | try_statement + | expression_statement + ; statement_block - : '{' LT!* statement_list? LT!* '}' - ; + : '{' LT!* statement_list? LT!* '}' + ; variable_statement - : 'var' LT!* variable_declaration_list (LT | ';')! - ; + : 'var' LT!* variable_declaration_list (LT | ';')! + ; empty_statement - : ';' - ; + : ';' + ; expression_statement - : expression (LT | ';')! - ; + : expression (LT | ';')! + ; iteration_statement - : do_while_statement - | while_statement - | for_statement - | for_in_statement - ; + : do_while_statement + | while_statement + | for_statement + | for_in_statement + ; continue_statement - : 'continue' Identifier? (LT | ';')! - ; + : 'continue' Identifier? (LT | ';')! + ; break_statement - : 'break' Identifier? (LT | ';')! - ; + : 'break' Identifier? (LT | ';')! + ; return_statement - : 'return' expression? (LT | ';')! - ; + : 'return' expression? (LT | ';')! + ; switchStatement : 'switch' LT!* '(' LT!* expression LT!* ')' LT!* caseBlock - ; + ; throw_statement : 'throw' expression (LT | ';')! - ; + ; try_statement : 'try' LT!* '{' LT!* statement_list LT!* '}' LT!* (finally_clause | catch_clause (LT!* finally_clause)?) @@ -1956,120 +2038,128 @@ parse_statement (void) reset_temp_name (); if (tok.type == TOK_CLOSE_BRACE) - { - lexer_save_token (tok); - return; - } + { + lexer_save_token (tok); + return; + } if (tok.type == TOK_OPEN_BRACE) + { + skip_newlines (); + if (tok.type != TOK_CLOSE_BRACE) { - skip_newlines (); - if (tok.type != TOK_CLOSE_BRACE) - { - parse_statement_list (); - next_token_must_be (TOK_CLOSE_BRACE); - } - return; + parse_statement_list (); + next_token_must_be (TOK_CLOSE_BRACE); } + return; + } if (is_keyword (KW_VAR)) - { - skip_newlines (); - parse_variable_declaration_list (NULL); - return; - } + { + skip_newlines (); + parse_variable_declaration_list (NULL); + return; + } if (tok.type == TOK_SEMICOLON) - { - return; - } + { + return; + } if (is_keyword (KW_IF)) - { - parse_if_statement (); - return; - } + { + parse_if_statement (); + return; + } if (is_keyword (KW_DO)) - { - parse_do_while_statement (); - return; - } + { + parse_do_while_statement (); + return; + } if (is_keyword (KW_WHILE)) - { - parse_while_statement (); - return; - } + { + parse_while_statement (); + return; + } if (is_keyword (KW_FOR)) - { - parse_for_or_for_in_statement (); - return; - } + { + parse_for_or_for_in_statement (); + return; + } if (is_keyword (KW_CONTINUE)) + { + must_be_inside_but_not_in ((uint8_t[]) { - must_be_inside_but_not_in ((uint8_t[]){NESTING_ITERATIONAL, NESTING_SWITCH}, 2, - NESTING_FUNCTION); - add_to_rewritable_opcodes (REWRITABLE_CONTINUE, opcode_counter); - DUMP_OPCODE_1 (jmp_up, INVALID_VALUE); - return; - } + NESTING_ITERATIONAL, NESTING_SWITCH + }, 2, + NESTING_FUNCTION); + add_to_rewritable_opcodes (REWRITABLE_CONTINUE, opcode_counter); + DUMP_OPCODE_1 (jmp_up, INVALID_VALUE); + return; + } if (is_keyword (KW_BREAK)) + { + must_be_inside_but_not_in ((uint8_t[]) { - must_be_inside_but_not_in ((uint8_t[]){NESTING_ITERATIONAL, NESTING_SWITCH}, 2, - NESTING_FUNCTION); - add_to_rewritable_opcodes (REWRITABLE_BREAK, opcode_counter); - DUMP_OPCODE_1 (jmp_down, INVALID_VALUE); - return; - } + NESTING_ITERATIONAL, NESTING_SWITCH + }, 2, + NESTING_FUNCTION); + add_to_rewritable_opcodes (REWRITABLE_BREAK, opcode_counter); + DUMP_OPCODE_1 (jmp_down, INVALID_VALUE); + return; + } if (is_keyword (KW_RETURN)) + { + T_IDX expr; + tok = lexer_next_token (); + if (tok.type != TOK_SEMICOLON) { - T_IDX expr; - tok = lexer_next_token (); - if (tok.type != TOK_SEMICOLON) - { - expr = parse_expression (); - DUMP_OPCODE_1 (retval, expr); - } - else - DUMP_VOID_OPCODE (ret); - return; + expr = parse_expression (); + DUMP_OPCODE_1 (retval, expr); } + else + { + DUMP_VOID_OPCODE (ret); + } + return; + } if (is_keyword (KW_WITH)) - { - parse_with_statement (); - return; - } + { + parse_with_statement (); + return; + } if (is_keyword (KW_SWITCH)) - { - parse_switch_statement (); - return; - } + { + parse_switch_statement (); + return; + } if (is_keyword (KW_THROW)) + { + JERRY_UNIMPLEMENTED (); + } + if (is_keyword (KW_TRY)) + { + parse_try_statement (); + return; + } + if (tok.type == TOK_NAME) + { + token saved = tok; + skip_newlines (); + if (tok.type == TOK_COLON) { + // STMT_LABELLED; JERRY_UNIMPLEMENTED (); } - if (is_keyword (KW_TRY)) - { - parse_try_statement (); - return; - } - if (tok.type == TOK_NAME) - { - token saved = tok; - skip_newlines (); - if (tok.type == TOK_COLON) - { - // STMT_LABELLED; - JERRY_UNIMPLEMENTED (); - } - else - { - lexer_save_token (tok); - tok = saved; - parse_expression (); - return; - } - } - else + else { + lexer_save_token (tok); + tok = saved; parse_expression (); return; } + } + else + { + parse_expression (); + return; + } } /* source_element @@ -2080,9 +2170,13 @@ static void parse_source_element (void) { if (is_keyword (KW_FUNCTION)) + { parse_function_declaration (); + } else + { parse_statement (); + } } /* source_element_list @@ -2098,17 +2192,23 @@ parse_source_element_list (void) DUMP_OPCODE_2 (reg_var_decl, min_temp_name, INVALID_VALUE); while (tok.type != TOK_EOF && tok.type != TOK_CLOSE_BRACE) - { - parse_source_element (); - skip_newlines (); - } + { + parse_source_element (); + skip_newlines (); + } lexer_save_token (tok); if (max_temp_name > min_temp_name) + { REWRITE_OPCODE_2 (reg_var_decl_loc, reg_var_decl, min_temp_name, max_temp_name - 1); + } else if (max_temp_name == min_temp_name) + { REWRITE_OPCODE_2 (reg_var_decl_loc, reg_var_decl, min_temp_name, max_temp_name); + } else + { JERRY_UNREACHABLE (); + } finish_scope (); optimizer_reorder_scope ((uint16_t) (reg_var_decl_loc + 1), opcode_counter); } diff --git a/tests/jerry/N.for.js b/tests/jerry/N.for.js new file mode 100644 index 000000000..1f7297285 --- /dev/null +++ b/tests/jerry/N.for.js @@ -0,0 +1,35 @@ +// 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. + +var i = 0; +for (; i < 100; i++) {} +assert (i == 100); + +for (var j = 0; j < 100; j++) {} +assert (i == 100); + +// for (i = 0;;) { +// if (i == 100) { +// // break; +// // assert (0); +// } +// i++; +// } +assert (i == 100); + +for (i = 0; i < 10; i++) { + for (j = 0; j < 10; j++) {} +} +assert (i == 100); +assert (j == 100);