diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index 1d1368560..cfee36440 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -1694,7 +1694,7 @@ read_meta_opcode_counter (opcode_meta_type expected_type, /**< expected type of } /* read_meta_opcode_counter */ #define GETOP_DEF_1(a, name, field1) \ - inline opcode_t getop_##name (idx_t arg1) \ + opcode_t getop_##name (idx_t arg1) \ { \ opcode_t opdata; \ opdata.op_idx = __op__idx_##name; \ @@ -1703,7 +1703,7 @@ read_meta_opcode_counter (opcode_meta_type expected_type, /**< expected type of } #define GETOP_DEF_2(a, name, field1, field2) \ - inline opcode_t getop_##name (idx_t arg1, idx_t arg2) \ + opcode_t getop_##name (idx_t arg1, idx_t arg2) \ { \ opcode_t opdata; \ opdata.op_idx = __op__idx_##name; \ @@ -1713,7 +1713,7 @@ read_meta_opcode_counter (opcode_meta_type expected_type, /**< expected type of } #define GETOP_DEF_3(a, name, field1, field2, field3) \ - inline opcode_t getop_##name (idx_t arg1, idx_t arg2, idx_t arg3) \ + opcode_t getop_##name (idx_t arg1, idx_t arg2, idx_t arg3) \ { \ opcode_t opdata; \ opdata.op_idx = __op__idx_##name; \ diff --git a/src/libintstructs/lp-string.h b/src/libintstructs/lp-string.h index 266b56862..2f7d5593c 100644 --- a/src/libintstructs/lp-string.h +++ b/src/libintstructs/lp-string.h @@ -22,7 +22,7 @@ typedef struct { ecma_length_t length; - const ecma_char_t *str; + ecma_char_t *str; } __packed lp_string; diff --git a/src/libintstructs/stack.h b/src/libintstructs/stack.h index 5b5b024d1..6a3d35950 100644 --- a/src/libintstructs/stack.h +++ b/src/libintstructs/stack.h @@ -260,6 +260,9 @@ do { set_##NAME##_stack_head ((NAME##_stack_data_type) (I), VALUE); } while (0) #define STACK_INCR_HEAD(NAME, I) \ do { STACK_SET_HEAD (NAME, I, (NAME##_stack_value_type) (STACK_HEAD (NAME, I) + 1)); } while (0) +#define STACK_DECR_HEAD(NAME, I) \ +do { STACK_SET_HEAD (NAME, I, (NAME##_stack_value_type) (STACK_HEAD (NAME, I) - 1)); } while (0) + #define STACK_TOP(NAME) \ STACK_HEAD (NAME, 1) diff --git a/src/libjsparser/lexer.c b/src/libjsparser/lexer.c index 8435898c4..f2fd57f78 100644 --- a/src/libjsparser/lexer.c +++ b/src/libjsparser/lexer.c @@ -26,7 +26,7 @@ static token empty_token = { .type = TOK_EMPTY, .uid = 0, - .locus = 0 + .loc = 0 }; static bool allow_dump_lines = false; @@ -63,6 +63,19 @@ is_empty (token tok) return tok.type == TOK_EMPTY; } +static locus +current_locus (void) +{ + if (token_start == NULL) + { + return (locus) (buffer - buffer_start - 1); + } + else + { + return (locus) (token_start - buffer_start); + } +} + static char get_char (size_t i) { @@ -93,28 +106,16 @@ dump_current_line (void) } static token -create_token (token_type type, size_t loc __unused, uint8_t uid) +create_token (token_type type, uint8_t uid) { return (token) { .type = type, - .locus = loc, + .loc = current_locus (), .uid = uid }; } -static token -create_token_from_current_token (token_type type, uint8_t uid) -{ - return create_token (type, (size_t) (token_start - buffer_start), uid); -} - -static token -create_token_from_buffer_state (token_type type, uint8_t uid) -{ - return create_token (type, (size_t) (buffer - buffer_start), uid); -} - static bool current_token_equals_to (const char *str) { @@ -151,187 +152,187 @@ decode_keyword (void) { if (current_token_equals_to ("break")) { - return create_token_from_current_token (TOK_KEYWORD, KW_BREAK); + return create_token (TOK_KEYWORD, KW_BREAK); } if (current_token_equals_to ("case")) { - return create_token_from_current_token (TOK_KEYWORD, KW_CASE); + return create_token (TOK_KEYWORD, KW_CASE); } if (current_token_equals_to ("catch")) { - return create_token_from_current_token (TOK_KEYWORD, KW_CATCH); + return create_token (TOK_KEYWORD, KW_CATCH); } if (current_token_equals_to ("class")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("const")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("continue")) { - return create_token_from_current_token (TOK_KEYWORD, KW_CONTINUE); + return create_token (TOK_KEYWORD, KW_CONTINUE); } if (current_token_equals_to ("debugger")) { - return create_token_from_current_token (TOK_KEYWORD, KW_DEBUGGER); + return create_token (TOK_KEYWORD, KW_DEBUGGER); } if (current_token_equals_to ("default")) { - return create_token_from_current_token (TOK_KEYWORD, KW_DEFAULT); + return create_token (TOK_KEYWORD, KW_DEFAULT); } if (current_token_equals_to ("delete")) { - return create_token_from_current_token (TOK_KEYWORD, KW_DELETE); + return create_token (TOK_KEYWORD, KW_DELETE); } if (current_token_equals_to ("do")) { - return create_token_from_current_token (TOK_KEYWORD, KW_DO); + return create_token (TOK_KEYWORD, KW_DO); } if (current_token_equals_to ("else")) { - return create_token_from_current_token (TOK_KEYWORD, KW_ELSE); + return create_token (TOK_KEYWORD, KW_ELSE); } if (current_token_equals_to ("enum")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("export")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("extends")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("false")) { - return create_token_from_current_token (TOK_BOOL, false); + return create_token (TOK_BOOL, false); } if (current_token_equals_to ("finally")) { - return create_token_from_current_token (TOK_KEYWORD, KW_FINALLY); + return create_token (TOK_KEYWORD, KW_FINALLY); } if (current_token_equals_to ("for")) { - return create_token_from_current_token (TOK_KEYWORD, KW_FOR); + return create_token (TOK_KEYWORD, KW_FOR); } if (current_token_equals_to ("function")) { - return create_token_from_current_token (TOK_KEYWORD, KW_FUNCTION); + return create_token (TOK_KEYWORD, KW_FUNCTION); } if (current_token_equals_to ("if")) { - return create_token_from_current_token (TOK_KEYWORD, KW_IF); + return create_token (TOK_KEYWORD, KW_IF); } if (current_token_equals_to ("instanceof")) { - return create_token_from_current_token (TOK_KEYWORD, KW_INSTANCEOF); + return create_token (TOK_KEYWORD, KW_INSTANCEOF); } if (current_token_equals_to ("interface")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("in")) { - return create_token_from_current_token (TOK_KEYWORD, KW_IN); + return create_token (TOK_KEYWORD, KW_IN); } if (current_token_equals_to ("import")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("implements")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("let")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("new")) { - return create_token_from_current_token (TOK_KEYWORD, KW_NEW); + return create_token (TOK_KEYWORD, KW_NEW); } if (current_token_equals_to ("null")) { - return create_token_from_current_token (TOK_NULL, 0); + return create_token (TOK_NULL, 0); } if (current_token_equals_to ("package")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("private")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("protected")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("public")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("return")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RETURN); + return create_token (TOK_KEYWORD, KW_RETURN); } if (current_token_equals_to ("static")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("super")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("switch")) { - return create_token_from_current_token (TOK_KEYWORD, KW_SWITCH); + return create_token (TOK_KEYWORD, KW_SWITCH); } if (current_token_equals_to ("this")) { - return create_token_from_current_token (TOK_KEYWORD, KW_THIS); + return create_token (TOK_KEYWORD, KW_THIS); } if (current_token_equals_to ("throw")) { - return create_token_from_current_token (TOK_KEYWORD, KW_THROW); + return create_token (TOK_KEYWORD, KW_THROW); } if (current_token_equals_to ("true")) { - return create_token_from_current_token (TOK_BOOL, true); + return create_token (TOK_BOOL, true); } if (current_token_equals_to ("try")) { - return create_token_from_current_token (TOK_KEYWORD, KW_TRY); + return create_token (TOK_KEYWORD, KW_TRY); } if (current_token_equals_to ("typeof")) { - return create_token_from_current_token (TOK_KEYWORD, KW_TYPEOF); + return create_token (TOK_KEYWORD, KW_TYPEOF); } if (current_token_equals_to ("var")) { - return create_token_from_current_token (TOK_KEYWORD, KW_VAR); + return create_token (TOK_KEYWORD, KW_VAR); } if (current_token_equals_to ("void")) { - return create_token_from_current_token (TOK_KEYWORD, KW_VOID); + return create_token (TOK_KEYWORD, KW_VOID); } if (current_token_equals_to ("while")) { - return create_token_from_current_token (TOK_KEYWORD, KW_WHILE); + return create_token (TOK_KEYWORD, KW_WHILE); } if (current_token_equals_to ("with")) { - return create_token_from_current_token (TOK_KEYWORD, KW_WITH); + return create_token (TOK_KEYWORD, KW_WITH); } if (current_token_equals_to ("yield")) { - return create_token_from_current_token (TOK_KEYWORD, KW_RESERVED); + return create_token (TOK_KEYWORD, KW_RESERVED); } if (current_token_equals_to ("undefined")) { - return create_token_from_current_token (TOK_UNDEFINED, 0); + return create_token (TOK_UNDEFINED, 0); } return empty_token; } @@ -345,19 +346,19 @@ convert_current_token_to_token (token_type tt) { if (current_token_equals_to_lp (STACK_ELEMENT (strings, i))) { - return create_token_from_current_token (tt, i); + return create_token (tt, i); } } const lp_string str = (lp_string) { .length = (uint8_t) (buffer - token_start), - .str = (const ecma_char_t *) token_start + .str = (ecma_char_t *) token_start }; STACK_PUSH (strings, str); - return create_token_from_current_token (tt, (idx_t) (STACK_SIZE (strings) - 1)); + return create_token (tt, (idx_t) (STACK_SIZE (strings) - 1)); } static token @@ -370,7 +371,7 @@ convert_seen_num_to_token (ecma_number_t num) { if (STACK_ELEMENT (numbers, i) == num) { - return create_token_from_current_token (TOK_NUMBER, STACK_ELEMENT (num_ids, i)); + return create_token (TOK_NUMBER, STACK_ELEMENT (num_ids, i)); } } @@ -378,7 +379,7 @@ convert_seen_num_to_token (ecma_number_t num) STACK_PUSH (num_ids, num_id); STACK_PUSH (numbers, num); - return create_token_from_current_token (TOK_NUMBER, num_id); + return create_token (TOK_NUMBER, num_id); } const lp_string * @@ -458,7 +459,7 @@ consume_char (void) do \ { \ buffer += NUM; \ - return create_token_from_buffer_state (TOK, 0); \ + return create_token (TOK, 0); \ } \ while (0) @@ -641,7 +642,7 @@ parse_number (void) if (res <= 255) { - known_token = create_token_from_current_token (TOK_SMALL_INT, (uint8_t) res); + known_token = create_token (TOK_SMALL_INT, (uint8_t) res); token_start = NULL; return known_token; } @@ -735,7 +736,7 @@ parse_number (void) if (res <= 255) { - known_token = create_token_from_current_token (TOK_SMALL_INT, (uint8_t) res); + known_token = create_token (TOK_SMALL_INT, (uint8_t) res); token_start = NULL; return known_token; } @@ -910,12 +911,12 @@ lexer_next_token_private (void) if (c == '\n') { consume_char (); - return create_token_from_buffer_state (TOK_NEWLINE, 0); + return create_token (TOK_NEWLINE, 0); } if (c == '\0') { - return create_token_from_buffer_state (TOK_EOF, 0); + return create_token (TOK_EOF, 0); } if (c == '\'' || c == '"') @@ -1078,9 +1079,18 @@ lexer_run_first_pass (void) } void -lexer_locus_to_line_and_column (size_t locus, size_t *line, size_t *column) +lexer_seek (size_t locus) { JERRY_ASSERT (locus < buffer_size); + JERRY_ASSERT (token_start == NULL); + + buffer = buffer_start + locus; +} + +void +lexer_locus_to_line_and_column (size_t locus, size_t *line, size_t *column) +{ + JERRY_ASSERT (locus <= buffer_size); const char *buf; size_t l = 0, c = 0; for (buf = buffer_start; (size_t) (buf - buffer_start) < locus; buf++) diff --git a/src/libjsparser/lexer.h b/src/libjsparser/lexer.h index 59099f447..d002e49de 100644 --- a/src/libjsparser/lexer.h +++ b/src/libjsparser/lexer.h @@ -134,13 +134,14 @@ typedef uint8_t token_type; #define TOK_UNDEFINED 57 // undefined #define TOK_EMPTY 58 +typedef size_t locus; /* Represents the contents of a token. */ typedef struct { token_type type; uint8_t uid; - size_t locus; + locus loc; } __packed token; @@ -166,7 +167,8 @@ uint8_t lexer_get_nums_count (void); void lexer_adjust_num_ids (void); -void lexer_locus_to_line_and_column (size_t, size_t *, size_t *); +void lexer_seek (locus); +void lexer_locus_to_line_and_column (locus, size_t *, size_t *); void lexer_dump_line (size_t); const char *lexer_keyword_to_string (keyword); const char *lexer_token_type_to_string (token_type); diff --git a/src/libjsparser/parse-error.h b/src/libjsparser/parse-error.h index 2e79a018f..2e4a7ef4d 100644 --- a/src/libjsparser/parse-error.h +++ b/src/libjsparser/parse-error.h @@ -18,7 +18,7 @@ #define PARSE_ERROR(MESSAGE, LOCUS) do { \ size_t line, column; \ - lexer_locus_to_line_and_column ((size_t) (LOCUS), &line, &column); \ + lexer_locus_to_line_and_column ((locus) (LOCUS), &line, &column); \ lexer_dump_line (line); \ __printf ("\n"); \ for (size_t i = 0; i < column; i++) { \ @@ -30,12 +30,12 @@ } while (0) #define PARSE_WARN(MESSAGE, LOCUS) do { \ size_t line, column; \ - lexer_locus_to_line_and_column ((size_t) (LOCUS), &line, &column); \ + lexer_locus_to_line_and_column ((locus) (LOCUS), &line, &column); \ __printf ("WARNING: Ln %d, Col %d: %s\n", line + 1, column + 1, MESSAGE); \ } while (0) #define PARSE_ERROR_VARG(MESSAGE, LOCUS, ...) do { \ size_t line, column; \ - lexer_locus_to_line_and_column ((size_t) (LOCUS), &line, &column); \ + lexer_locus_to_line_and_column ((locus) (LOCUS), &line, &column); \ lexer_dump_line (line); \ __printf ("\n"); \ for (size_t i = 0; i < column; i++) { \ @@ -49,7 +49,7 @@ } while (0) #define PARSE_SORRY(MESSAGE, LOCUS) do { \ size_t line, column; \ - lexer_locus_to_line_and_column ((size_t) (LOCUS), &line, &column); \ + lexer_locus_to_line_and_column ((locus) (LOCUS), &line, &column); \ lexer_dump_line (line); \ __printf ("\n"); \ for (size_t i = 0; i < column; i++) { \ diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index c30f89896..995f62971 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -121,6 +121,12 @@ enum }; STATIC_STACK (ops, uint8_t, opcode_t) +enum +{ + locs_global_size +}; +STATIC_STACK (locs, uint8_t, locus) + enum { opcode_counter = 0, @@ -267,9 +273,9 @@ do { \ STACK_CHECK_USAGE (IDX); \ } while (0) -#define EMIT_ERROR(MESSAGE) PARSE_ERROR(MESSAGE, TOK().locus) -#define EMIT_SORRY(MESSAGE) PARSE_SORRY(MESSAGE, TOK().locus) -#define EMIT_ERROR_VARG(MESSAGE, ...) PARSE_ERROR_VARG(MESSAGE, TOK().locus, __VA_ARGS__) +#define EMIT_ERROR(MESSAGE) PARSE_ERROR(MESSAGE, TOK().loc) +#define EMIT_SORRY(MESSAGE) PARSE_SORRY(MESSAGE, TOK().loc) +#define EMIT_ERROR_VARG(MESSAGE, ...) PARSE_ERROR_VARG(MESSAGE, TOK().loc, __VA_ARGS__) #define NESTING_TO_STRING(I) (I == NESTING_FUNCTION \ ? "function" \ @@ -292,7 +298,7 @@ argument_list_type; static void parse_expression (void); static void parse_statement (void); static void parse_assignment_expression (void); -static void parse_source_element_list (void); +static void parse_source_element_list (bool); static void parse_argument_list (argument_list_type, idx_t, idx_t); static uint8_t @@ -473,7 +479,7 @@ token_after_newlines_must_be (token_type tt) } } -static inline void +static void token_after_newlines_must_be_keyword (keyword kw) { skip_newlines (); @@ -570,7 +576,7 @@ fill_intrinsics (void) lp_string str = (lp_string) { .length = 6, - .str = (const ecma_char_t *) "assert" + .str = (ecma_char_t *) "assert" }; intrinsic_dumper dumper = (intrinsic_dumper) { @@ -761,7 +767,7 @@ parse_property_assignment (void) token_after_newlines_must_be (TOK_OPEN_BRACE); skip_newlines (); - parse_source_element_list (); + parse_source_element_list (false); token_after_newlines_must_be (TOK_CLOSE_BRACE); DUMP_VOID_OPCODE (ret); @@ -784,7 +790,7 @@ parse_property_assignment (void) token_after_newlines_must_be (TOK_OPEN_BRACE); skip_newlines (); - parse_source_element_list (); + parse_source_element_list (false); token_after_newlines_must_be (TOK_CLOSE_BRACE); DUMP_VOID_OPCODE (ret); @@ -1066,7 +1072,7 @@ parse_function_declaration (void) skip_newlines (); push_nesting (NESTING_FUNCTION); - parse_source_element_list (); + parse_source_element_list (false); pop_nesting (NESTING_FUNCTION); next_token_must_be (TOK_CLOSE_BRACE); @@ -1118,7 +1124,7 @@ parse_function_expression (void) skip_newlines (); push_nesting (NESTING_FUNCTION); - parse_source_element_list (); + parse_source_element_list (false); pop_nesting (NESTING_FUNCTION); token_after_newlines_must_be (TOK_CLOSE_BRACE); @@ -2312,7 +2318,6 @@ parse_variable_declaration (void) current_token_must_be (TOK_NAME); STACK_PUSH (IDX, token_data ()); - DUMP_OPCODE_1 (var_decl, ID(1)); skip_newlines (); if (token_is (TOK_EQ)) @@ -3182,11 +3187,201 @@ parse_source_element (void) STACK_CHECK_USAGE (IDX); } +static void +skip_optional_name_and_braces (void) +{ + if (token_is (TOK_NAME)) + { + token_after_newlines_must_be (TOK_OPEN_PAREN); + } + else + { + current_token_must_be (TOK_OPEN_PAREN); + } + + while (!token_is (TOK_CLOSE_BRACE)) + { + skip_newlines (); + } +} + +static void +skip_braces (void) +{ + STACK_DECLARE_USAGE (U8) + + current_token_must_be (TOK_OPEN_BRACE); + + STACK_PUSH (U8, 1); + + while (STACK_TOP (U8) > 0) + { + skip_newlines (); + if (token_is (TOK_OPEN_BRACE)) + { + STACK_INCR_HEAD (U8, 1); + } + else if (token_is (TOK_CLOSE_BRACE)) + { + STACK_DECR_HEAD (U8, 1); + } + } + + STACK_DROP (U8,1); + STACK_CHECK_USAGE (U8); +} + +static void +skip_function (void) +{ + skip_newlines (); + skip_optional_name_and_braces (); + skip_newlines (); + skip_braces (); +} + +static void +skip_squares (void) +{ + STACK_DECLARE_USAGE (U8); + + current_token_must_be (TOK_OPEN_SQUARE); + + STACK_PUSH (U8, 1); + + while (STACK_TOP (U8) > 0) + { + skip_newlines (); + if (token_is (TOK_OPEN_SQUARE)) + { + STACK_INCR_HEAD (U8, 1); + } + else if (token_is (TOK_CLOSE_SQUARE)) + { + STACK_DECR_HEAD (U8, 1); + } + } + + STACK_DROP (U8,1); + STACK_CHECK_USAGE (U8); +} + +static void +skip_parens (void) +{ + STACK_DECLARE_USAGE (U8); + + current_token_must_be (TOK_OPEN_PAREN); + + STACK_PUSH (U8, 1); + + while (STACK_TOP (U8) > 0) + { + skip_newlines (); + if (token_is (TOK_OPEN_PAREN)) + { + STACK_INCR_HEAD (U8, 1); + } + else if (token_is (TOK_CLOSE_PAREN)) + { + STACK_DECR_HEAD (U8, 1); + } + } + + STACK_DROP (U8,1); + STACK_CHECK_USAGE (U8); +} + +static void +preparse_var_decls (void) +{ + assert_keyword (KW_VAR); + + skip_newlines (); + while (!token_is (TOK_NEWLINE) && !token_is (TOK_SEMICOLON)) + { + if (token_is (TOK_NAME)) + { + DUMP_OPCODE_1 (var_decl, token_data ()); + skip_token (); + continue; + } + else if (token_is (TOK_EQ)) + { + while (!token_is (TOK_COMMA) && !token_is (TOK_NEWLINE) && !token_is (TOK_SEMICOLON)) + { + if (is_keyword (KW_FUNCTION)) + { + skip_function (); + } + else if (token_is (TOK_OPEN_BRACE)) + { + skip_braces (); + } + else if (token_is (TOK_OPEN_SQUARE)) + { + skip_squares (); + } + else if (token_is (TOK_OPEN_PAREN)) + { + skip_parens (); + } + skip_token (); + } + } + else if (!token_is (TOK_COMMA)) + { + EMIT_ERROR ("Expected ','"); + } + else + { + skip_token (); + continue; + } + } +} + +static void +preparse_scope (bool is_global) +{ + STACK_DECLARE_USAGE (locs); + STACK_DECLARE_USAGE (U8) + STACK_DECLARE_USAGE (U16) + + STACK_PUSH (locs, TOK ().loc); + STACK_PUSH (U8, is_global ? TOK_EOF : TOK_CLOSE_BRACE); + + STACK_PUSH (U16, OPCODE_COUNTER ()); + DUMP_VOID_OPCODE (nop); /* use strict. */ + + while (!token_is (STACK_TOP (U8))) + { + if (token_is (TOK_STRING) && lp_string_equal_s (lexer_get_string_by_id (token_data ()), "use strict")) + { + REWRITE_OPCODE_3 (STACK_TOP (U16), meta, OPCODE_META_TYPE_STRICT_CODE, INVALID_VALUE, INVALID_VALUE); + } + else if (is_keyword (KW_VAR)) + { + preparse_var_decls (); + } + skip_newlines (); + } + + lexer_seek (STACK_TOP (locs)); + STACK_DROP (locs, 1); + STACK_DROP (U8, 1); + STACK_DROP (U16, 1); + + STACK_CHECK_USAGE (U8); + STACK_CHECK_USAGE (U16); + STACK_CHECK_USAGE (locs); +} + /* source_element_list : source_element (LT!* source_element)* ; */ static void -parse_source_element_list (void) +parse_source_element_list (bool is_global) { // U16 reg_var_decl_loc; STACK_DECLARE_USAGE (U16) @@ -3197,6 +3392,9 @@ parse_source_element_list (void) STACK_PUSH (U16, OPCODE_COUNTER ()); DUMP_OPCODE_2 (reg_var_decl, MIN_TEMP_NAME (), INVALID_VALUE); + preparse_scope (is_global); + + skip_newlines (); while (!token_is (TOK_EOF) && !token_is (TOK_CLOSE_BRACE)) { parse_source_element (); @@ -3222,7 +3420,7 @@ parser_parse_program (void) STACK_DECLARE_USAGE (IDX) skip_newlines (); - parse_source_element_list (); + parse_source_element_list (true); skip_newlines (); JERRY_ASSERT (token_is (TOK_EOF)); @@ -3257,6 +3455,7 @@ parser_init (const char *source, size_t source_size, bool show_opcodes) STACK_INIT (uint16_t, U16); STACK_INIT (opcode_counter_t, rewritable_continue); STACK_INIT (opcode_counter_t, rewritable_break); + STACK_INIT (locus, locs); HASH_INIT (intrinsics, 1); @@ -3314,6 +3513,7 @@ parser_free (void) STACK_FREE (U16); STACK_FREE (rewritable_continue); STACK_FREE (rewritable_break); + STACK_FREE (locs); HASH_FREE (intrinsics); diff --git a/src/liboptimizer/serializer.c b/src/liboptimizer/serializer.c index e21a75b5b..99e9bac5a 100644 --- a/src/liboptimizer/serializer.c +++ b/src/liboptimizer/serializer.c @@ -91,10 +91,11 @@ serializer_print_opcodes (void) void serializer_adjust_strings (void) { - for (uint8_t i = 0; i < bytecode_data.strs_count; i++) + for (uint8_t i = 0; i < bytecode_data.strs_count; ++i) { - const ecma_length_t len = bytecode_data.strings[i].length; - ((ecma_char_t *) (bytecode_data.strings[i]).str)[len] = '\0'; + ecma_length_t len = bytecode_data.strings[i].length; + ecma_char_t *str = bytecode_data.strings[i].str; + str[len] = '\0'; } } diff --git a/tests/unit/test_preparser.c b/tests/unit/test_preparser.c new file mode 100644 index 000000000..ab10352c7 --- /dev/null +++ b/tests/unit/test_preparser.c @@ -0,0 +1,60 @@ +/* Copyright 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "globals.h" +#include "mem-allocator.h" +#include "opcodes.h" +#include "deserializer.h" +#include "common.h" +#include "parser.h" +#include "jerry-libc.h" + +/** + * Unit test's main function. + */ +int +main( int __unused argc, + char __unused **argv) +{ + char program[] = {'a','=','1',';','v','a','r',' ','a',';','\0'}; + bool is_ok; + + mem_init(); + deserializer_init (); + parser_init (program, __strlen (program), true); + parser_parse_program (); + parser_free (); + + if (!opcodes_equal(deserialize_bytecode (), (opcode_t[]) { + [0] = getop_reg_var_decl (1, 2), // var tmp1 .. tmp2; + [1] = getop_nop (), // ; + [2] = getop_var_decl (0), // var a; + [3] = getop_assignment (1, 1, 1), // tmp1 = 1: SMALLINT; + [4] = getop_assignment (0, 4, 1), // a = tmp1: TYPEOF(tmp1); + [5] = getop_exitval (0) // exit 0; + }, 6)) + { + is_ok = false; + } + else + { + is_ok = true; + } + + deserializer_free (); + mem_finalize (false); + + return (is_ok ? 0 : 1); +} /* main */