Implement the core of let/const statement. (#3239)

This patch implements the core part of let/const statements. Redeclarations are correctly
detected and separate contexts are correctly created for these statements. Register
optimizations are also emplyed whenever possible.

Lots of features are still missing:
 - checking the var statements in eval
 - const are treated as lets
 - single statement checks are missing
 - export declarations are exported as vars, let/const export is not supported

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2019-10-25 18:08:10 +02:00
committed by Dániel Bátyai
parent 4b352758c1
commit 3d797b8836
33 changed files with 1997 additions and 217 deletions
+14 -4
View File
@@ -192,6 +192,8 @@
#define PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION 3
/* PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION must be <= 4 */
#define PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION 4
/* PARSER_BLOCK_CONTEXT_STACK_ALLOCATION must be <= 3 */
#define PARSER_BLOCK_CONTEXT_STACK_ALLOCATION 1
/* PARSER_WITH_CONTEXT_STACK_ALLOCATION must be <= 4 */
#define PARSER_WITH_CONTEXT_STACK_ALLOCATION 1
/* PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION must be <= 4 */
@@ -244,6 +246,10 @@
VM_OC_PUSH_ELISON | VM_OC_PUT_STACK) \
CBC_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL, -1, \
VM_OC_BRANCH_IF_STRICT_EQUAL) \
CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1, \
VM_OC_PUSH_NULL | VM_OC_PUT_STACK) \
CBC_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT, \
PARSER_BLOCK_CONTEXT_STACK_ALLOCATION, VM_OC_BLOCK_CREATE_CONTEXT) \
\
/* Basic opcodes. Note: These 4 opcodes must me in this order */ \
CBC_OPCODE (CBC_PUSH_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
@@ -260,8 +266,6 @@
VM_OC_PUSH_TRUE | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_PUSH_FALSE, CBC_NO_FLAG, 1, \
VM_OC_PUSH_FALSE | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1, \
VM_OC_PUSH_NULL | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_PUSH_THIS, CBC_NO_FLAG, 1, \
VM_OC_PUSH_THIS | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_PUSH_NUMBER_0, CBC_NO_FLAG, 1, \
@@ -302,6 +306,10 @@
VM_OC_NONE) \
CBC_OPCODE (CBC_INIT_LOCAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_NONE) \
CBC_OPCODE (CBC_CREATE_VAR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \
CBC_OPCODE (CBC_SET_VAR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \
CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0, \
VM_OC_NONE) \
CBC_OPCODE (CBC_RETURN, CBC_NO_FLAG, -1, \
@@ -508,8 +516,8 @@
VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \
CBC_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT, PARSER_TRY_CONTEXT_STACK_ALLOCATION, \
VM_OC_TRY) \
CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1, \
VM_OC_THROW_REFERENCE_ERROR) \
CBC_OPCODE (CBC_EXT_TRY_CREATE_ENV, CBC_NO_FLAG, 0, \
VM_OC_BLOCK_CREATE_CONTEXT) \
CBC_FORWARD_BRANCH (CBC_EXT_CATCH, 1, \
VM_OC_CATCH) \
CBC_OPCODE (CBC_EXT_PUSH_UNDEFINED_BASE, CBC_NO_FLAG, 1, \
@@ -554,6 +562,8 @@
VM_OC_SET_SETTER | VM_OC_GET_STACK_LITERAL) \
CBC_OPCODE (CBC_EXT_RESOLVE_BASE, CBC_NO_FLAG, 0, \
VM_OC_RESOLVE_BASE_FOR_CALL) \
CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1, \
VM_OC_THROW_REFERENCE_ERROR) \
\
/* Class opcodes */ \
CBC_OPCODE (CBC_EXT_INHERIT_AND_SET_CONSTRUCTOR, CBC_NO_FLAG, 0, \
+3
View File
@@ -74,6 +74,9 @@ typedef enum
LEXER_FLAG_SOURCE_PTR = (1 << 2), /**< the literal is directly referenced in the source code
* (no need to allocate memory) */
LEXER_FLAG_LATE_INIT = (1 << 3), /**< initialize this variable after the byte code is freed */
#if ENABLED (JERRY_ES2015)
LEXER_FLAG_GLOBAL = (1 << 4), /**< this local identifier is not a let or const declaration */
#endif /* ENABLED (JERRY_ES2015) */
} lexer_literal_status_flags_t;
/**
+9 -2
View File
@@ -1476,7 +1476,14 @@ lexer_process_char_literal (parser_context_t *context_p, /**< context */
{
scope_stack_p--;
if (scope_stack_p->map_from == literal_index)
#if ENABLED (JERRY_ES2015)
bool cond = (scope_stack_p->map_from == literal_index
&& scope_stack_p->map_to != PARSER_SCOPE_STACK_FUNC);
#else /* ENABLED (JERRY_ES2015) */
bool cond = (scope_stack_p->map_from == literal_index);
#endif /* ENABLED (JERRY_ES2015) */
if (cond)
{
JERRY_ASSERT (scope_stack_p->map_to >= PARSER_REGISTER_START
|| (literal_p->status_flags & LEXER_FLAG_USED));
@@ -2322,7 +2329,7 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
context_p->token.literal_is_reserved = false;
context_p->token.lit_location.type = LEXER_IDENT_LITERAL;
context_p->token.lit_location.has_escape = false;
lexer_construct_literal_object (context_p, &lexer_default_literal, lexer_default_literal.type);
lexer_construct_literal_object (context_p, &lexer_default_literal, literal_type);
context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC);
return;
}
+6 -19
View File
@@ -151,10 +151,6 @@ typedef enum
LEXER_COMMA_SEP_LIST, /**< comma separated bracketed expression list */
LEXER_SCAN_SWITCH, /**< special value for switch pre-scan */
LEXER_CLASS_CONSTRUCTOR, /**< special value for class constructor method */
#if ENABLED (JERRY_ES2015)
LEXER_FOR_IN_OF, /**< special value during for in/of statmenet scanning */
LEXER_LITERAL_OF, /**< 'of' literal */
#endif /* ENABLED (JERRY_ES2015) */
#if !ENABLED (JERRY_ES2015)
/* Future reserved words: these keywords
@@ -164,6 +160,9 @@ typedef enum
LEXER_KEYW_CLASS, /**< class */
LEXER_KEYW_EXTENDS, /**< extends */
LEXER_KEYW_SUPER, /**< super */
#if ENABLED (JERRY_ES2015)
LEXER_KEYW_LET, /**< let */
#endif /* ENABLED (JERRY_ES2015) */
LEXER_KEYW_CONST, /**< const */
LEXER_KEYW_EXPORT, /**< export */
LEXER_KEYW_IMPORT, /**< import */
@@ -190,25 +189,13 @@ typedef enum
LEXER_KEYW_PACKAGE, /**< package */
LEXER_KEYW_PROTECTED, /**< protected */
#if ENABLED (JERRY_ES2015)
/* Context dependent strict reserved words:
* See also: ECMA-262 v6, 11.6.2.1 */
#define LEXER_FIRST_CONTEXT_DEPENDENT_RESERVED_WORD LEXER_KEYW_STATIC
LEXER_KEYW_STATIC, /**< static */
#else /* !ENABLED (JERRY_ES2015) */
/* Context dependent strict reserved words:
* See also: ECMA-262 v6, 11.6.2.1 */
#define LEXER_FIRST_CONTEXT_DEPENDENT_RESERVED_WORD
#endif /* ENABLED (JERRY_ES2015) */
/* Context dependent future strict reserved words:
* See also: ECMA-262 v6, 11.6.2.1 */
#define LEXER_FIRST_CONTEXT_DEPENDENT_FUTURE_RESERVED_WORD LEXER_KEYW_LET
LEXER_KEYW_LET, /**< let */
LEXER_KEYW_YIELD, /**< yield */
#if !ENABLED (JERRY_ES2015)
LEXER_KEYW_STATIC, /**< static */
LEXER_KEYW_LET, /**< let */
#endif /* !ENABLED (JERRY_ES2015) */
LEXER_KEYW_YIELD, /**< yield */
LEXER_KEYW_STATIC, /**< static */
} lexer_token_type_t;
#define LEXER_NEWLINE_LS_PS_BYTE_1 0xe2
+8
View File
@@ -595,6 +595,14 @@ parser_parse_class (parser_context_t *context_p, /**< context */
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
#if ENABLED (JERRY_ES2015)
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
}
#endif /* ENABLED (JERRY_ES2015) */
class_ident_index = context_p->lit_object.index;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
+13 -9
View File
@@ -64,9 +64,10 @@ typedef enum
PARSER_DEBUGGER_BREAKPOINT_APPENDED = (1u << 15), /**< pending (unsent) breakpoint
* info is available */
#if ENABLED (JERRY_ES2015)
PARSER_FUNCTION_HAS_REST_PARAM = (1u << 16), /**< function has rest parameter */
PARSER_IS_ARROW_FUNCTION = (1u << 18), /**< an arrow function is parsed */
PARSER_ARROW_PARSE_ARGS = (1u << 19), /**< parse the argument list of an arrow function */
PARSER_INSIDE_BLOCK = (1u << 16), /**< script has a lexical environment for let and const */
PARSER_IS_ARROW_FUNCTION = (1u << 17), /**< an arrow function is parsed */
PARSER_ARROW_PARSE_ARGS = (1u << 18), /**< parse the argument list of an arrow function */
PARSER_FUNCTION_HAS_REST_PARAM = (1u << 19), /**< function has rest parameter */
/* These four status flags must be in this order. See PARSER_CLASS_PARSE_OPTS_OFFSET. */
PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed (this value must be kept in
* in sync with ECMA_PARSE_CLASS_CONSTRUCTOR) */
@@ -371,8 +372,11 @@ typedef struct parser_saved_context_t
parser_mem_data_t literal_pool_data; /**< literal list */
parser_scope_stack *scope_stack_p; /**< scope stack */
uint16_t scope_stack_size; /**< size of scope stack */
uint16_t scope_stack_top; /**< current top of scope stack */
uint16_t scope_stack_reg_top; /**< current top register of scope stack */
uint16_t scope_stack_top; /**< preserved top of scope stack */
uint16_t scope_stack_reg_top; /**< preserved top register of scope stack */
#if ENABLED (JERRY_ES2015)
uint16_t scope_stack_global_end; /**< end of global declarations of a function */
#endif /* ENABLED (JERRY_ES2015) */
#ifndef JERRY_NDEBUG
uint16_t context_stack_depth; /**< current context stack depth */
@@ -440,6 +444,9 @@ typedef struct
uint16_t scope_stack_size; /**< size of scope stack */
uint16_t scope_stack_top; /**< current top of scope stack */
uint16_t scope_stack_reg_top; /**< current top register of scope stack */
#if ENABLED (JERRY_ES2015)
uint16_t scope_stack_global_end; /**< end of global declarations of a function */
#endif /* ENABLED (JERRY_ES2015) */
uint8_t stack_top_uint8; /**< top byte stored on the stack */
#ifndef JERRY_NDEBUG
@@ -615,10 +622,6 @@ void parser_parse_super_class_context_end (parser_context_t *context_p, bool is_
* @{
*/
void scanner_raise_error (parser_context_t *context_p);
void *scanner_malloc (parser_context_t *context_p, size_t size);
void scanner_free (void *ptr, size_t size);
void scanner_release_next (parser_context_t *context_p, size_t size);
void scanner_set_active (parser_context_t *context_p);
void scanner_release_active (parser_context_t *context_p, size_t size);
@@ -627,6 +630,7 @@ void scanner_seek (parser_context_t *context_p);
void scanner_reverse_info_list (parser_context_t *context_p);
void scanner_cleanup (parser_context_t *context_p);
bool scanner_is_context_needed (parser_context_t *context_p);
void scanner_create_variables (parser_context_t *context_p, size_t size);
void scanner_get_location (scanner_location_t *location_p, parser_context_t *context_p);
+2 -2
View File
@@ -438,7 +438,7 @@ parser_module_parse_import_clause (parser_context_t *context_p) /**< parser cont
ecma_string_t *import_name_p = NULL;
ecma_string_t *local_name_p = NULL;
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL);
uint16_t import_name_index = context_p->lit_object.index;
uint16_t local_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS;
@@ -454,7 +454,7 @@ parser_module_parse_import_clause (parser_context_t *context_p) /**< parser cont
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
}
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL);
local_name_index = context_p->lit_object.index;
+277 -7
View File
@@ -57,12 +57,18 @@ typedef enum
{
PARSER_STATEMENT_START,
PARSER_STATEMENT_BLOCK,
#if ENABLED (JERRY_ES2015)
PARSER_STATEMENT_BLOCK_CONTEXT,
#endif /* ENABLED (JERRY_ES2015) */
PARSER_STATEMENT_LABEL,
PARSER_STATEMENT_IF,
PARSER_STATEMENT_ELSE,
/* From switch -> for-in : break target statements */
PARSER_STATEMENT_SWITCH,
PARSER_STATEMENT_SWITCH_NO_DEFAULT,
#if ENABLED (JERRY_ES2015)
PARSER_STATEMENT_SWITCH_BLOCK_CONTEXT,
#endif /* ENABLED (JERRY_ES2015) */
/* From do-while -> for->in : continue target statements */
PARSER_STATEMENT_DO_WHILE,
PARSER_STATEMENT_WHILE,
@@ -78,6 +84,40 @@ typedef enum
PARSER_STATEMENT_TRY,
} parser_statement_type_t;
#if !ENABLED (JERRY_ES2015)
/**
* Get the expected depth of a function call.
*/
#define JERRY_GET_EXPECTED_DEPTH(context_p) 0
#else /* ENABLED (JERRY_ES2015) */
/**
* Get the expected depth of a function call.
*/
#define JERRY_GET_EXPECTED_DEPTH(context_p) \
(((context_p)->status_flags & PARSER_INSIDE_BLOCK) ? PARSER_BLOCK_CONTEXT_STACK_ALLOCATION : 0)
/**
* Block statement.
*/
typedef struct
{
uint16_t scope_stack_top; /**< preserved top of scope stack */
uint16_t scope_stack_reg_top; /**< preserved top register of scope stack */
} parser_block_statement_t;
/**
* Context of block statement.
*/
typedef struct
{
parser_branch_t branch; /**< branch to the end */
} parser_block_context_t;
#endif /* !ENABLED (JERRY_ES2015) */
/**
* Loop statement.
*/
@@ -110,6 +150,10 @@ typedef struct
{
parser_branch_t default_branch; /**< branch to the default case */
parser_branch_node_t *branch_list_p; /**< branches of case statements */
#if ENABLED (JERRY_ES2015)
uint16_t scope_stack_top; /**< preserved top of scope stack */
uint16_t scope_stack_reg_top; /**< preserved top register of scope stack */
#endif /* ENABLED (JERRY_ES2015) */
} parser_switch_statement_t;
/**
@@ -190,8 +234,15 @@ parser_statement_length (uint8_t type) /**< type of statement */
{
static const uint8_t statement_lengths[] =
{
#if ENABLED (JERRY_ES2015)
/* PARSER_STATEMENT_BLOCK */
(uint8_t) (sizeof (parser_block_statement_t) + 1),
/* PARSER_STATEMENT_BLOCK_CONTEXT */
(uint8_t) (sizeof (parser_block_statement_t) + sizeof (parser_block_context_t) + 1),
#else /* !ENABLED (JERRY_ES2015) */
/* PARSER_STATEMENT_BLOCK */
1,
#endif /* ENABLED (JERRY_ES2015) */
/* PARSER_STATEMENT_LABEL */
(uint8_t) (sizeof (parser_label_statement_t) + 1),
/* PARSER_STATEMENT_IF */
@@ -202,6 +253,10 @@ parser_statement_length (uint8_t type) /**< type of statement */
(uint8_t) (sizeof (parser_switch_statement_t) + sizeof (parser_loop_statement_t) + 1),
/* PARSER_STATEMENT_SWITCH_NO_DEFAULT */
(uint8_t) (sizeof (parser_switch_statement_t) + sizeof (parser_loop_statement_t) + 1),
#if ENABLED (JERRY_ES2015)
/* PARSER_STATEMENT_SWITCH_BLOCK_CONTEXT */
(uint8_t) (sizeof (parser_block_context_t) + 1),
#endif /* ENABLED (JERRY_ES2015) */
/* PARSER_STATEMENT_DO_WHILE */
(uint8_t) (sizeof (parser_do_while_statement_t) + sizeof (parser_loop_statement_t) + 1),
/* PARSER_STATEMENT_WHILE */
@@ -293,7 +348,9 @@ parser_parse_enclosed_expr (parser_context_t *context_p) /**< context */
static void
parser_parse_var_statement (parser_context_t *context_p) /**< context */
{
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_VAR);
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_VAR
|| context_p->token.type == LEXER_KEYW_LET
|| context_p->token.type == LEXER_KEYW_CONST);
while (true)
{
@@ -313,6 +370,14 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
}
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
#if ENABLED (JERRY_ES2015)
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
}
#endif /* ENABLED (JERRY_ES2015) */
lexer_next_token (context_p);
if (context_p->token.type == LEXER_ASSIGN)
@@ -368,6 +433,14 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
#if ENABLED (JERRY_ES2015)
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
}
#endif /* ENABLED (JERRY_ES2015) */
if (context_p->lit_object.type == LEXER_LITERAL_OBJECT_ARGUMENTS)
{
context_p->status_flags |= PARSER_ARGUMENTS_NOT_NEEDED;
@@ -1185,6 +1258,33 @@ parser_parse_switch_statement_start (parser_context_t *context_p) /**< context *
parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED);
}
#if ENABLED (JERRY_ES2015)
switch_statement.scope_stack_top = context_p->scope_stack_top;
switch_statement.scope_stack_reg_top = context_p->scope_stack_reg_top;
if (context_p->next_scanner_info_p->source_p == context_p->source_p - 1)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
if (scanner_is_context_needed (context_p))
{
parser_block_context_t block_context;
#ifndef JERRY_NDEBUG
PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
#endif /* !JERRY_NDEBUG */
parser_emit_cbc_forward_branch (context_p,
CBC_BLOCK_CREATE_CONTEXT,
&block_context.branch);
parser_stack_push (context_p, &block_context, sizeof (parser_block_context_t));
parser_stack_push_uint8 (context_p, PARSER_STATEMENT_SWITCH_BLOCK_CONTEXT);
}
scanner_create_variables (context_p, sizeof (scanner_info_t));
}
#endif /* ENABLED (JERRY_ES2015) */
JERRY_ASSERT (context_p->next_scanner_info_p->source_p == context_p->source_p
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_SWITCH);
@@ -1201,6 +1301,14 @@ parser_parse_switch_statement_start (parser_context_t *context_p) /**< context *
parser_emit_cbc (context_p, CBC_POP);
parser_flush_cbc (context_p);
#if ENABLED (JERRY_ES2015)
parser_block_statement_t block_statement;
block_statement.scope_stack_top = context_p->scope_stack_top;
block_statement.scope_stack_reg_top = context_p->scope_stack_reg_top;
parser_stack_push (context_p, &block_statement, sizeof (parser_block_statement_t));
#endif /* ENABLED (JERRY_ES2015) */
parser_stack_push_uint8 (context_p, PARSER_STATEMENT_BLOCK);
parser_stack_iterator_init (context_p, &context_p->last_statement);
return;
@@ -1349,6 +1457,11 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
parser_stack_iterator_skip (&iterator, 1);
parser_stack_iterator_read (&iterator, &try_statement, sizeof (parser_try_statement_t));
#if ENABLED (JERRY_ES2015)
context_p->scope_stack_top = try_statement.scope_stack_top;
context_p->scope_stack_reg_top = try_statement.scope_stack_reg_top;
#endif /* ENABLED (JERRY_ES2015) */
lexer_next_token (context_p);
if (try_statement.type == parser_finally_block)
@@ -1368,8 +1481,10 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
if (try_statement.type == parser_catch_block)
{
#if !ENABLED (JERRY_ES2015)
context_p->scope_stack_top = try_statement.scope_stack_top;
context_p->scope_stack_reg_top = try_statement.scope_stack_reg_top;
#endif /* !ENABLED (JERRY_ES2015) */
if (context_p->token.type != LEXER_KEYW_FINALLY)
{
@@ -1423,12 +1538,18 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
bool block_found = false;
#endif /* !JERRY_NDEBUG */
if (context_p->next_scanner_info_p->source_p == context_p->source_p
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK)
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
#ifndef JERRY_NDEBUG
block_found = true;
#endif /* !JERRY_NDEBUG */
if (scanner_is_context_needed (context_p))
{
parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV);
}
scanner_create_variables (context_p, sizeof (scanner_info_t));
}
@@ -1474,6 +1595,20 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
parser_emit_cbc_ext_forward_branch (context_p,
CBC_EXT_FINALLY,
&try_statement.branch);
#if ENABLED (JERRY_ES2015)
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
if (scanner_is_context_needed (context_p))
{
parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV);
}
scanner_create_variables (context_p, sizeof (scanner_info_t));
}
#endif /* ENABLED (JERRY_ES2015) */
}
lexer_next_token (context_p);
@@ -1585,6 +1720,9 @@ parser_parse_break_statement (parser_context_t *context_p) /**< context */
|| type == PARSER_STATEMENT_FOR_OF
#endif /* ENABLED (JERRY_ES2015) */
|| type == PARSER_STATEMENT_WITH
#if ENABLED (JERRY_ES2015)
|| type == PARSER_STATEMENT_BLOCK_CONTEXT
#endif /* ENABLED (JERRY_ES2015) */
|| type == PARSER_STATEMENT_TRY)
{
opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT;
@@ -1629,6 +1767,9 @@ parser_parse_break_statement (parser_context_t *context_p) /**< context */
|| type == PARSER_STATEMENT_FOR_OF
#endif /* ENABLED (JERRY_ES2015) */
|| type == PARSER_STATEMENT_WITH
#if ENABLED (JERRY_ES2015)
|| type == PARSER_STATEMENT_BLOCK_CONTEXT
#endif /* ENABLED (JERRY_ES2015) */
|| type == PARSER_STATEMENT_TRY)
{
opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT;
@@ -1723,6 +1864,9 @@ parser_parse_continue_statement (parser_context_t *context_p) /**< context */
#endif /* ENABLED (JERRY_ES2015) */
if (type == PARSER_STATEMENT_WITH
#if ENABLED (JERRY_ES2015)
|| type == PARSER_STATEMENT_BLOCK_CONTEXT
#endif /* ENABLED (JERRY_ES2015) */
|| type == PARSER_STATEMENT_TRY
|| for_in_of_was_seen)
{
@@ -1782,6 +1926,9 @@ parser_parse_continue_statement (parser_context_t *context_p) /**< context */
}
if (type == PARSER_STATEMENT_WITH
#if ENABLED (JERRY_ES2015)
|| type == PARSER_STATEMENT_BLOCK_CONTEXT
#endif /* ENABLED (JERRY_ES2015) */
|| type == PARSER_STATEMENT_TRY)
{
opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT;
@@ -1993,6 +2140,10 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
break;
}
case LEXER_KEYW_VAR:
#if ENABLED (JERRY_ES2015)
case LEXER_KEYW_LET:
case LEXER_KEYW_CONST:
#endif /* ENABLED (JERRY_ES2015) */
{
context_p->status_flags |= PARSER_MODULE_STORE_IDENT;
parser_parse_var_statement (context_p);
@@ -2151,7 +2302,10 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
lexer_lit_location_t lit_location;
uint32_t status_flags = context_p->status_flags;
JERRY_ASSERT (context_p->stack_depth == 0);
JERRY_ASSERT (context_p->stack_depth == JERRY_GET_EXPECTED_DEPTH (context_p));
#ifndef JERRY_NDEBUG
JERRY_ASSERT (context_p->context_stack_depth == context_p->stack_depth);
#endif /* !JERRY_NDEBUG */
lit_location = context_p->token.lit_location;
@@ -2246,6 +2400,8 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
&& context_p->token.type != LEXER_LEFT_BRACE
&& context_p->token.type != LEXER_RIGHT_BRACE
&& context_p->token.type != LEXER_KEYW_VAR
&& context_p->token.type != LEXER_KEYW_LET
&& context_p->token.type != LEXER_KEYW_CONST
&& context_p->token.type != LEXER_KEYW_FUNCTION
&& context_p->token.type != LEXER_KEYW_CASE
&& context_p->token.type != LEXER_KEYW_DEFAULT)
@@ -2265,6 +2421,8 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
&& context_p->token.type != LEXER_LEFT_BRACE
&& context_p->token.type != LEXER_RIGHT_BRACE
&& context_p->token.type != LEXER_KEYW_VAR
&& context_p->token.type != LEXER_KEYW_LET
&& context_p->token.type != LEXER_KEYW_CONST
&& context_p->token.type != LEXER_KEYW_FUNCTION
&& context_p->token.type != LEXER_KEYW_CASE
&& context_p->token.type != LEXER_KEYW_DEFAULT)
@@ -2301,13 +2459,49 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
case LEXER_LEFT_BRACE:
{
parser_stack_push_uint8 (context_p, PARSER_STATEMENT_BLOCK);
uint8_t block_type = PARSER_STATEMENT_BLOCK;
#if ENABLED (JERRY_ES2015)
parser_block_statement_t block_statement;
block_statement.scope_stack_top = context_p->scope_stack_top;
block_statement.scope_stack_reg_top = context_p->scope_stack_reg_top;
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
if (scanner_is_context_needed (context_p))
{
parser_block_context_t block_context;
#ifndef JERRY_NDEBUG
PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
#endif /* !JERRY_NDEBUG */
parser_emit_cbc_forward_branch (context_p,
CBC_BLOCK_CREATE_CONTEXT,
&block_context.branch);
parser_stack_push (context_p, &block_context, sizeof (parser_block_context_t));
block_type = PARSER_STATEMENT_BLOCK_CONTEXT;
}
scanner_create_variables (context_p, sizeof (scanner_info_t));
}
parser_stack_push (context_p, &block_statement, sizeof (parser_block_statement_t));
#endif /* ENABLED (JERRY_ES2015) */
parser_stack_push_uint8 (context_p, block_type);
parser_stack_iterator_init (context_p, &context_p->last_statement);
lexer_next_token (context_p);
continue;
}
case LEXER_KEYW_VAR:
#if ENABLED (JERRY_ES2015)
case LEXER_KEYW_LET:
case LEXER_KEYW_CONST:
#endif /* ENABLED (JERRY_ES2015) */
{
parser_parse_var_statement (context_p);
break;
@@ -2409,6 +2603,23 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
CBC_EXT_TRY_CREATE_CONTEXT,
&try_statement.branch);
#if ENABLED (JERRY_ES2015)
try_statement.scope_stack_top = context_p->scope_stack_top;
try_statement.scope_stack_reg_top = context_p->scope_stack_reg_top;
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
if (scanner_is_context_needed (context_p))
{
parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV);
}
scanner_create_variables (context_p, sizeof (scanner_info_t));
}
#endif /* ENABLED (JERRY_ES2015) */
parser_stack_push (context_p, &try_statement, sizeof (parser_try_statement_t));
parser_stack_push_uint8 (context_p, PARSER_STATEMENT_TRY);
parser_stack_iterator_init (context_p, &context_p->last_statement);
@@ -2575,9 +2786,43 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
if (context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK)
{
parser_stack_pop_uint8 (context_p);
#if ENABLED (JERRY_ES2015)
parser_block_statement_t block_statement;
parser_stack_pop (context_p, &block_statement, sizeof (parser_block_statement_t));
context_p->scope_stack_top = block_statement.scope_stack_top;
context_p->scope_stack_reg_top = block_statement.scope_stack_reg_top;
#endif /* ENABLED (JERRY_ES2015) */
parser_stack_iterator_init (context_p, &context_p->last_statement);
lexer_next_token (context_p);
}
#if ENABLED (JERRY_ES2015)
else if (context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK_CONTEXT)
{
parser_block_statement_t block_statement;
parser_block_context_t block_context;
parser_stack_pop_uint8 (context_p);
parser_stack_pop (context_p, &block_statement, sizeof (parser_block_statement_t));
parser_stack_pop (context_p, &block_context, sizeof (parser_block_context_t));
context_p->scope_stack_top = block_statement.scope_stack_top;
context_p->scope_stack_reg_top = block_statement.scope_stack_reg_top;
PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
#ifndef JERRY_NDEBUG
PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
#endif /* !JERRY_NDEBUG */
parser_emit_cbc (context_p, CBC_CONTEXT_END);
parser_set_branch_to_current_position (context_p, &block_context.branch);
parser_stack_iterator_init (context_p, &context_p->last_statement);
lexer_next_token (context_p);
}
#endif /* ENABLED (JERRY_ES2015) */
else if (context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH
|| context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH_NO_DEFAULT)
{
@@ -2590,6 +2835,11 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
parser_stack_pop (context_p, &switch_statement, sizeof (parser_switch_statement_t));
parser_stack_iterator_init (context_p, &context_p->last_statement);
#if ENABLED (JERRY_ES2015)
context_p->scope_stack_top = switch_statement.scope_stack_top;
context_p->scope_stack_reg_top = switch_statement.scope_stack_reg_top;
#endif /* ENABLED (JERRY_ES2015) */
JERRY_ASSERT (switch_statement.branch_list_p == NULL);
if (!has_default)
@@ -2599,6 +2849,26 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
parser_set_breaks_to_current_position (context_p, loop.branch_list_p);
lexer_next_token (context_p);
#if ENABLED (JERRY_ES2015)
if (context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH_BLOCK_CONTEXT)
{
parser_block_context_t block_context;
parser_stack_pop_uint8 (context_p);
parser_stack_pop (context_p, &block_context, sizeof (parser_block_context_t));
PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
#ifndef JERRY_NDEBUG
PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
#endif /* !JERRY_NDEBUG */
parser_emit_cbc (context_p, CBC_CONTEXT_END);
parser_set_branch_to_current_position (context_p, &block_context.branch);
parser_stack_iterator_init (context_p, &context_p->last_statement);
}
#endif /* ENABLED (JERRY_ES2015) */
}
else if (context_p->stack_top_uint8 == PARSER_STATEMENT_TRY)
{
@@ -2762,9 +3032,9 @@ consume_last_statement:
}
}
JERRY_ASSERT (context_p->stack_depth == 0);
JERRY_ASSERT (context_p->stack_depth == JERRY_GET_EXPECTED_DEPTH (context_p));
#ifndef JERRY_NDEBUG
JERRY_ASSERT (context_p->context_stack_depth == 0);
JERRY_ASSERT (context_p->context_stack_depth == context_p->stack_depth);
#endif /* !JERRY_NDEBUG */
parser_stack_pop_uint8 (context_p);
+4
View File
@@ -1117,6 +1117,10 @@ parser_error_to_string (parser_error_t error) /**< error code */
{
return "Rest parameter may not have a default initializer.";
}
case PARSER_ERR_VARIABLE_REDECLARED:
{
return "Local variable is redeclared.";
}
#endif /* ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
case PARSER_ERR_FILE_NOT_FOUND:
+52 -1
View File
@@ -1813,6 +1813,9 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
context.scope_stack_size = 0;
context.scope_stack_top = 0;
context.scope_stack_reg_top = 0;
#if ENABLED (JERRY_ES2015)
context.scope_stack_global_end = 0;
#endif /* ENABLED (JERRY_ES2015) */
#ifndef JERRY_NDEBUG
context.context_stack_depth = 0;
@@ -1896,12 +1899,51 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
}
else
{
JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
JERRY_ASSERT (context.next_scanner_info_p->source_p == source_p - 1
&& context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
scanner_create_variables (&context, sizeof (scanner_function_info_t));
#if ENABLED (JERRY_ES2015)
if (context.next_scanner_info_p->source_p == source_p)
{
JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
if (scanner_is_context_needed (&context))
{
parser_branch_t branch;
#ifndef JERRY_NDEBUG
PARSER_PLUS_EQUAL_U16 (context.context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
#endif /* !JERRY_NDEBUG */
parser_emit_cbc_forward_branch (&context,
CBC_BLOCK_CREATE_CONTEXT,
&branch);
parser_stack_push (&context, &branch, sizeof (parser_branch_t));
context.status_flags |= PARSER_INSIDE_BLOCK;
}
scanner_create_variables (&context, sizeof (scanner_info_t));
context.scope_stack_global_end = context.scope_stack_top;
}
#endif /* ENABLED (JERRY_ES2015) */
}
parser_parse_statements (&context);
#if ENABLED (JERRY_ES2015)
if (context.status_flags & PARSER_INSIDE_BLOCK)
{
parser_branch_t branch;
parser_stack_pop (&context, &branch, sizeof (parser_branch_t));
parser_emit_cbc (&context, CBC_CONTEXT_END);
parser_set_branch_to_current_position (&context, &branch);
parser_flush_cbc (&context);
}
#endif /* ENABLED (JERRY_ES2015) */
/* When the parsing is successful, only the
* dummy value can be remained on the stack. */
JERRY_ASSERT (context.stack_top_uint8 == CBC_MAXIMUM_BYTE_VALUE
@@ -2022,6 +2064,9 @@ parser_save_context (parser_context_t *context_p, /**< context */
saved_context_p->scope_stack_size = context_p->scope_stack_size;
saved_context_p->scope_stack_top = context_p->scope_stack_top;
saved_context_p->scope_stack_reg_top = context_p->scope_stack_reg_top;
#if ENABLED (JERRY_ES2015)
saved_context_p->scope_stack_global_end = context_p->scope_stack_global_end;
#endif /* ENABLED (JERRY_ES2015) */
#ifndef JERRY_NDEBUG
saved_context_p->context_stack_depth = context_p->context_stack_depth;
@@ -2046,6 +2091,9 @@ parser_save_context (parser_context_t *context_p, /**< context */
context_p->scope_stack_size = 0;
context_p->scope_stack_top = 0;
context_p->scope_stack_reg_top = 0;
#if ENABLED (JERRY_ES2015)
context_p->scope_stack_global_end = 0;
#endif /* ENABLED (JERRY_ES2015) */
#ifndef JERRY_NDEBUG
context_p->context_stack_depth = 0;
@@ -2087,6 +2135,9 @@ parser_restore_context (parser_context_t *context_p, /**< context */
context_p->scope_stack_size = saved_context_p->scope_stack_size;
context_p->scope_stack_top = saved_context_p->scope_stack_top;
context_p->scope_stack_reg_top = saved_context_p->scope_stack_reg_top;
#if ENABLED (JERRY_ES2015)
context_p->scope_stack_global_end = saved_context_p->scope_stack_global_end;
#endif /* ENABLED (JERRY_ES2015) */
#ifndef JERRY_NDEBUG
context_p->context_stack_depth = saved_context_p->context_stack_depth;
+3
View File
@@ -112,6 +112,9 @@ typedef enum
PARSER_ERR_INVALID_RIGHT_SQUARE, /**< right square must terminate a block */
PARSER_ERR_DUPLICATED_LABEL, /**< duplicated label */
PARSER_ERR_OBJECT_PROPERTY_REDEFINED, /**< property of object literal redefined */
#if ENABLED (JERRY_ES2015)
PARSER_ERR_VARIABLE_REDECLARED, /**< a variable redeclared */
#endif /* ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_ES2015)
PARSER_ERR_MULTIPLE_CLASS_CONSTRUCTORS, /**< multiple class constructor */
@@ -45,8 +45,28 @@ typedef enum
SCANNER_LITERAL_IS_VAR = (1 << 2), /**< literal is var */
SCANNER_LITERAL_IS_FUNC = (1 << 3), /**< literal is function */
SCANNER_LITERAL_NO_REG = (1 << 4), /**< literal cannot be stored in register */
#if ENABLED (JERRY_ES2015)
SCANNER_LITERAL_IS_LET = (1 << 5), /**< literal is let */
SCANNER_LITERAL_IS_CONST = (1 << 6), /**< literal is const */
#endif /* ENABLED (JERRY_ES2015) */
} scanner_literal_type_flags_t;
#if ENABLED (JERRY_ES2015)
/**
* Tells whether the literal is let or const declaration.
*/
#define SCANNER_LITERAL_IS_LET_OR_CONST (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST)
#else /* !ENABLED (JERRY_ES2015) */
/**
* No literal is let or const declaration in ECMAScript 5.1.
*/
#define SCANNER_LITERAL_IS_LET_OR_CONST 0
#endif /* ENABLED (JERRY_ES2015) */
/**
* For statement descriptor.
*/
@@ -112,6 +132,14 @@ struct scanner_context_t
scanner_info_t *end_arguments_p; /**< position of end arguments */
};
void scanner_raise_error (parser_context_t *context_p);
#if ENABLED (JERRY_ES2015)
void scanner_raise_redeclaration_error (parser_context_t *context_p);
#endif /* ENABLED (JERRY_ES2015) */
void *scanner_malloc (parser_context_t *context_p, size_t size);
void scanner_free (void *ptr, size_t size);
size_t scanner_get_stream_size (scanner_info_t *info_p, size_t size);
scanner_info_t *scanner_insert_info (parser_context_t *context_p, const uint8_t *source_p, size_t size);
scanner_info_t *scanner_insert_info_before (parser_context_t *context_p, const uint8_t *source_p,
@@ -119,14 +147,22 @@ scanner_info_t *scanner_insert_info_before (parser_context_t *context_p, const u
scanner_literal_pool_t *scanner_push_literal_pool (parser_context_t *context_p, scanner_context_t *scanner_context_p,
uint16_t status_flags);
void scanner_pop_literal_pool (parser_context_t *context_p, scanner_context_t *scanner_context_p);
#if ENABLED (JERRY_ES2015)
void scanner_construct_global_block (parser_context_t *context_p, scanner_context_t *scanner_context_p);
#endif /* ENABLED (JERRY_ES2015) */
void scanner_filter_arguments (parser_context_t *context_p, scanner_context_t *scanner_context_p);
lexer_lit_location_t *scanner_add_custom_literal (parser_context_t *context_p, scanner_literal_pool_t *literal_pool_p,
const lexer_lit_location_t *literal_location_p);
lexer_lit_location_t *scanner_add_literal (parser_context_t *context_p, scanner_context_t *scanner_context_p);
void scanner_add_reference (parser_context_t *context_p, scanner_context_t *scanner_context_p);
void scanner_append_argument (parser_context_t *context_p, scanner_context_t *scanner_context_p);
#if ENABLED (JERRY_ES2015)
void scanner_detect_invalid_var (parser_context_t *context_p, scanner_context_t *scanner_context_p,
lexer_lit_location_t *var_literal_p);
#endif /* ENABLED (JERRY_ES2015) */
void scanner_detect_eval_call (parser_context_t *context_p, scanner_context_t *scanner_context_p);
/**
* @}
* @}
+565 -47
View File
@@ -43,6 +43,22 @@ scanner_raise_error (parser_context_t *context_p) /**< context */
JERRY_ASSERT (0);
} /* scanner_raise_error */
#if ENABLED (JERRY_ES2015)
/**
* Raise a variable redeclaration error.
*/
void
scanner_raise_redeclaration_error (parser_context_t *context_p)
{
scanner_info_t *info_p = scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_info_t));
info_p->type = SCANNER_TYPE_ERR_REDECLARED;
scanner_raise_error (context_p);
} /* scanner_raise_redeclaration_error */
#endif /* ENABLED (JERRY_ES2015) */
/**
* Allocate memory for scanner.
*
@@ -94,10 +110,17 @@ scanner_get_stream_size (scanner_info_t *info_p, /**< scanner info block */
{
switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
{
case SCANNER_STREAM_TYPE_VAR:
#if ENABLED (JERRY_ES2015)
case SCANNER_STREAM_TYPE_LET:
case SCANNER_STREAM_TYPE_CONST:
#endif /* ENABLED (JERRY_ES2015) */
case SCANNER_STREAM_TYPE_ARG:
case SCANNER_STREAM_TYPE_ARG_FUNC:
case SCANNER_STREAM_TYPE_VAR:
case SCANNER_STREAM_TYPE_FUNC:
#if ENABLED (JERRY_ES2015)
case SCANNER_STREAM_TYPE_VAR_FUNC:
#endif /* ENABLED (JERRY_ES2015) */
{
break;
}
@@ -404,7 +427,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
{
search_arguments = false;
if (type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC))
if (type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET_OR_CONST))
{
arguments_required = false;
}
@@ -416,8 +439,16 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
}
}
if (((type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)) && is_function)
|| (type & SCANNER_LITERAL_IS_LOCAL))
#if ENABLED (JERRY_ES2015)
if (is_function && (type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET)) == SCANNER_LITERAL_IS_FUNC)
{
type = (uint8_t) ((type & ~SCANNER_LITERAL_IS_FUNC) | SCANNER_LITERAL_IS_VAR);
literal_p->type = type;
}
#endif /* ENABLED (JERRY_ES2015) */
if ((is_function && (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)))
|| (type & (SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_IS_LET_OR_CONST)))
{
JERRY_ASSERT (is_function || !(literal_p->type & SCANNER_LITERAL_IS_ARG));
@@ -457,7 +488,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
prev_source_p = literal_p->char_p + literal_p->length;
if (is_function || !(type & SCANNER_LITERAL_IS_VAR))
if (is_function || !(type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC)))
{
continue;
}
@@ -475,7 +506,15 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
literal_location_p->type |= SCANNER_LITERAL_NO_REG;
}
type = (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC));
#if ENABLED (JERRY_ES2015)
if (literal_location_p->type & SCANNER_LITERAL_IS_LET_OR_CONST)
{
JERRY_ASSERT (!(type & SCANNER_LITERAL_IS_VAR));
type = 0;
}
#endif /* ENABLED (JERRY_ES2015) */
type = (uint8_t) (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC));
JERRY_ASSERT (type == 0 || !is_function);
literal_location_p->type = (uint8_t) (literal_location_p->type | type);
@@ -532,21 +571,17 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
data_p += sizeof (scanner_info_t);
JERRY_ASSERT (prev_literal_pool_p != NULL);
if (prev_literal_pool_p->no_declarations < no_declarations)
{
prev_literal_pool_p->no_declarations = (uint16_t) no_declarations;
}
}
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
prev_source_p = literal_pool_p->source_p - 1;
no_declarations = 0;
no_declarations = literal_pool_p->no_declarations;
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
|| (!((literal_p->type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)) && is_function)
&& !(literal_p->type & SCANNER_LITERAL_IS_LOCAL)))
|| (!(is_function && (literal_p->type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)))
&& !(literal_p->type & (SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_IS_LET_OR_CONST))))
{
continue;
}
@@ -575,6 +610,16 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
{
type = SCANNER_STREAM_TYPE_ARG;
}
#if ENABLED (JERRY_ES2015)
else if (literal_p->type & SCANNER_LITERAL_IS_LET)
{
type = SCANNER_STREAM_TYPE_LET;
}
else if (literal_p->type & SCANNER_LITERAL_IS_CONST)
{
type = SCANNER_STREAM_TYPE_CONST;
}
#endif /* ENABLED (JERRY_ES2015) */
if (literal_p->has_escape)
{
@@ -624,12 +669,192 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
JERRY_ASSERT (((uint8_t *) info_p) + compressed_size == data_p + 1);
}
if (!is_function && prev_literal_pool_p->no_declarations < no_declarations)
{
prev_literal_pool_p->no_declarations = (uint16_t) no_declarations;
}
scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p;
parser_list_free (&literal_pool_p->literal_pool);
scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
} /* scanner_pop_literal_pool */
#if ENABLED (JERRY_ES2015)
/**
* Extract certain (e.g. let/const) global declarations and construct a scanner info structure from them.
*/
void
scanner_construct_global_block (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p) /**< scanner context */
{
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
parser_list_iterator_t literal_iterator;
lexer_lit_location_t *literal_p;
bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0;
#if ENABLED (JERRY_DEBUGGER)
if (scanner_context_p->debugger_enabled)
{
/* When debugger is enabled, identifiers are not stored in registers. However,
* this does not affect 'eval' detection, so 'arguments' object is not created. */
no_reg = true;
}
#endif /* ENABLED (JERRY_DEBUGGER) */
JERRY_ASSERT (literal_pool_p->prev_p == NULL);
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
const uint8_t *prev_source_p = literal_pool_p->source_p;
size_t compressed_size = 1;
uint32_t no_declarations = literal_pool_p->no_declarations;
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
uint8_t type = literal_p->type;
if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
|| !(type & SCANNER_LITERAL_IS_LET_OR_CONST))
{
continue;
}
no_declarations++;
if (type & SCANNER_LITERAL_IS_FUNC)
{
JERRY_ASSERT (type & SCANNER_LITERAL_IS_LET);
no_declarations++;
type |= SCANNER_LITERAL_NO_REG;
literal_p->type = type;
}
else if (no_reg)
{
type |= SCANNER_LITERAL_NO_REG;
literal_p->type = type;
}
intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
if (diff >= 1 && diff <= UINT8_MAX)
{
compressed_size += 2 + 1;
}
else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
{
compressed_size += 2 + 2;
}
else
{
compressed_size += 2 + 1 + sizeof (const uint8_t *);
}
prev_source_p = literal_p->char_p + literal_p->length;
}
if (compressed_size <= 1)
{
return;
}
scanner_info_t *info_p;
compressed_size += sizeof (scanner_info_t);
info_p = scanner_insert_info (context_p, literal_pool_p->source_p + 1, compressed_size);
info_p->type = SCANNER_TYPE_BLOCK;
uint8_t *data_p = ((uint8_t *) info_p) + sizeof (scanner_info_t);
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
prev_source_p = literal_pool_p->source_p;
no_declarations = literal_pool_p->no_declarations;
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
|| !(literal_p->type & SCANNER_LITERAL_IS_LET_OR_CONST))
{
continue;
}
no_declarations++;
uint8_t type = SCANNER_STREAM_TYPE_LET;
if (literal_p->type & SCANNER_LITERAL_IS_CONST)
{
type = SCANNER_STREAM_TYPE_CONST;
}
else if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
{
type = SCANNER_STREAM_TYPE_VAR_FUNC;
no_declarations++;
}
if (literal_p->has_escape)
{
type |= SCANNER_STREAM_HAS_ESCAPE;
}
if (literal_p->type & SCANNER_LITERAL_NO_REG)
{
type |= SCANNER_STREAM_NO_REG;
}
literal_p->type = 0;
data_p[0] = type;
data_p[1] = (uint8_t) literal_p->length;
data_p += 3;
intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
if (diff >= 1 && diff <= UINT8_MAX)
{
data_p[-1] = (uint8_t) diff;
}
else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
{
if (diff < 0)
{
diff = -diff;
}
data_p[-3] |= SCANNER_STREAM_UINT16_DIFF;
data_p[-1] = (uint8_t) diff;
data_p[0] = (uint8_t) (diff >> 8);
data_p += 1;
}
else
{
data_p[-1] = 0;
memcpy (data_p, &literal_p->char_p, sizeof (const uint8_t *));
data_p += sizeof (const uint8_t *);
}
prev_source_p = literal_p->char_p + literal_p->length;
}
data_p[0] = SCANNER_STREAM_TYPE_END;
JERRY_ASSERT (((uint8_t *) info_p) + compressed_size == data_p + 1);
if (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
{
no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK;
}
literal_pool_p->no_declarations = (uint16_t) no_declarations;
} /* scanner_construct_global_block */
#endif /* ENABLED (JERRY_ES2015) */
/**
* Filter out the arguments from a literal pool.
*/
@@ -883,6 +1108,75 @@ scanner_detect_eval_call (parser_context_t *context_p, /**< context */
}
} /* scanner_detect_eval_call */
#if ENABLED (JERRY_ES2015)
/**
* Throws an error for invalid var statements.
*/
void
scanner_detect_invalid_var (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p, /**< scanner context */
lexer_lit_location_t *var_literal_p) /**< literal */
{
if (var_literal_p->type & (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST)
&& !(var_literal_p->type & SCANNER_LITERAL_IS_FUNC))
{
scanner_raise_redeclaration_error (context_p);
}
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
const uint8_t *char_p = var_literal_p->char_p;
prop_length_t length = var_literal_p->length;
while (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION))
{
literal_pool_p = literal_pool_p->prev_p;
parser_list_iterator_t literal_iterator;
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
lexer_lit_location_t *literal_p;
if (JERRY_LIKELY (!context_p->token.lit_location.has_escape))
{
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (literal_p->type & (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST)
&& literal_p->length == length)
{
if (JERRY_LIKELY (!literal_p->has_escape))
{
if (memcmp (literal_p->char_p, char_p, length) == 0)
{
scanner_raise_redeclaration_error (context_p);
return;
}
}
else if (lexer_compare_identifiers (literal_p->char_p, char_p, length))
{
scanner_raise_redeclaration_error (context_p);
return;
}
}
}
}
else
{
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (literal_p->type & (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST)
&& literal_p->length == length
&& lexer_compare_identifiers (literal_p->char_p, char_p, length))
{
scanner_raise_redeclaration_error (context_p);
return;
}
}
}
}
} /* scanner_detect_invalid_var */
#endif /* ENABLED (JERRY_ES2015) */
/**
* Reverse the scanner info chain after the scanning is completed.
*/
@@ -973,7 +1267,12 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
}
default:
{
#if ENABLED (JERRY_ES2015)
JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS
|| scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
#else /* !ENABLED (JERRY_ES2015) */
JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS);
#endif /* ENABLED (JERRY_ES2015) */
break;
}
}
@@ -986,6 +1285,158 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
context_p->active_scanner_info_p = NULL;
} /* scanner_cleanup */
#if ENABLED (JERRY_ES2015)
/**
* Finds the literal id of a function if its target is a var declaration
*
* @return function id - if the target of a function is a var declaration,
* negative value - otherwise
*/
static int32_t
scanner_get_function_target (parser_context_t *context_p) /**< context */
{
uint16_t literal_index = context_p->lit_object.index;
parser_scope_stack *scope_stack_start_p = context_p->scope_stack_p;
parser_scope_stack *scope_stack_p = scope_stack_start_p + context_p->scope_stack_top;
while (scope_stack_p > scope_stack_start_p)
{
scope_stack_p--;
if (scope_stack_p->map_from == literal_index
&& scope_stack_p->map_to != PARSER_SCOPE_STACK_FUNC)
{
if ((scope_stack_p - scope_stack_start_p) >= context_p->scope_stack_global_end
|| !(context_p->lit_object.literal_p->status_flags & LEXER_FLAG_GLOBAL))
{
return -1;
}
return scope_stack_p->map_to;
}
}
return -1;
} /* scanner_get_function_target */
#endif /* ENABLED (JERRY_ES2015) */
/**
* Checks whether a context needs to be created for a block.
*
* @return true - if context is needed,
* false - otherwise
*/
bool
scanner_is_context_needed (parser_context_t *context_p) /**< context */
{
scanner_info_t *info_p = context_p->next_scanner_info_p;
const uint8_t *data_p = ((const uint8_t *) info_p) + sizeof (scanner_info_t);
#if ENABLED (JERRY_ES2015)
lexer_lit_location_t literal;
#endif /* ENABLED (JERRY_ES2015) */
JERRY_ASSERT (info_p->type == SCANNER_TYPE_BLOCK);
uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
#if ENABLED (JERRY_ES2015)
literal.char_p = info_p->source_p - 1;
#endif /* ENABLED (JERRY_ES2015) */
while (data_p[0] != SCANNER_STREAM_TYPE_END)
{
uint32_t type = data_p[0] & SCANNER_STREAM_TYPE_MASK;
#if ENABLED (JERRY_ES2015)
JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
|| type == SCANNER_STREAM_TYPE_LET
|| type == SCANNER_STREAM_TYPE_CONST
|| type == SCANNER_STREAM_TYPE_FUNC
|| type == SCANNER_STREAM_TYPE_VAR_FUNC);
#else /* !ENABLED (JERRY_ES2015) */
JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR);
#endif /* ENABLED (JERRY_ES2015) */
size_t length;
if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
{
if (data_p[2] != 0)
{
#if ENABLED (JERRY_ES2015)
literal.char_p += data_p[2];
#endif /* ENABLED (JERRY_ES2015) */
length = 2 + 1;
}
else
{
#if ENABLED (JERRY_ES2015)
memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
#endif /* ENABLED (JERRY_ES2015) */
length = 2 + 1 + sizeof (const uint8_t *);
}
}
else
{
#if ENABLED (JERRY_ES2015)
int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
if (diff <= UINT8_MAX)
{
diff = -diff;
}
literal.char_p += diff;
#endif /* ENABLED (JERRY_ES2015) */
length = 2 + 2;
}
#if ENABLED (JERRY_ES2015)
if (type == SCANNER_STREAM_TYPE_FUNC)
{
literal.length = data_p[1];
literal.type = LEXER_IDENT_LITERAL;
literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
if (scanner_get_function_target (context_p) >= 0)
{
literal.char_p += data_p[1];
data_p += length;
continue;
}
}
#endif /* ENABLED (JERRY_ES2015) */
if (!(data_p[0] & SCANNER_STREAM_NO_REG)
&& scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
{
scope_stack_reg_top++;
}
else
{
#if ENABLED (JERRY_ES2015)
if (type != SCANNER_STREAM_TYPE_VAR_FUNC)
{
return true;
}
#else /* !ENABLED (JERRY_ES2015) */
return true;
#endif /* ENABLED (JERRY_ES2015) */
}
#if ENABLED (JERRY_ES2015)
literal.char_p += data_p[1];
#endif /* ENABLED (JERRY_ES2015) */
data_p += length;
}
return false;
} /* scanner_is_context_needed */
/**
* Description of "arguments" literal string.
*/
@@ -1111,64 +1562,124 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
scope_stack_p->map_from = context_p->lit_object.index;
uint16_t map_to;
uint16_t func_init_opcode = CBC_INIT_LOCAL;
if (!(data_p[0] & SCANNER_STREAM_NO_REG)
&& scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
#if ENABLED (JERRY_ES2015)
if (info_type == SCANNER_TYPE_FUNCTION)
{
map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top);
scope_stack_p->map_from = context_p->lit_object.index;
scope_stack_p->map_to = map_to;
scope_stack_reg_top++;
if (type != SCANNER_STREAM_TYPE_LET
&& type != SCANNER_STREAM_TYPE_CONST)
{
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_GLOBAL;
}
}
else
else if (type == SCANNER_STREAM_TYPE_FUNC)
{
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
map_to = context_p->lit_object.index;
int32_t target_id = scanner_get_function_target (context_p);
scope_stack_p->map_from = map_to;
scope_stack_p->map_to = map_to;
if (info_type == SCANNER_TYPE_FUNCTION)
if (target_id >= 0)
{
context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
map_to = (uint16_t) target_id;
scope_stack_p->map_to = PARSER_SCOPE_STACK_FUNC;
func_init_opcode = CBC_SET_VAR_FUNC;
}
}
else if (type == SCANNER_STREAM_TYPE_VAR_FUNC)
{
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_GLOBAL;
}
#endif /* ENABLED (JERRY_ES2015) */
if (type == SCANNER_STREAM_TYPE_VAR)
if (func_init_opcode == CBC_INIT_LOCAL)
{
if (!(data_p[0] & SCANNER_STREAM_NO_REG)
&& scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
{
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top);
parser_emit_cbc_literal (context_p, CBC_CREATE_VAR, map_to);
scope_stack_p->map_to = map_to;
scope_stack_reg_top++;
#if ENABLED (JERRY_ES2015)
func_init_opcode = CBC_SET_VAR_FUNC;
#endif /* ENABLED (JERRY_ES2015) */
}
else if (type == SCANNER_STREAM_TYPE_ARG || type == SCANNER_STREAM_TYPE_ARG_FUNC)
else
{
if (type == SCANNER_STREAM_TYPE_ARG)
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
map_to = context_p->lit_object.index;
scope_stack_p->map_to = map_to;
if (info_type == SCANNER_TYPE_FUNCTION)
{
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
parser_emit_cbc_literal_value (context_p,
CBC_INIT_LOCAL,
(uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top),
map_to);
context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
}
if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
switch (type)
{
scope_stack_reg_top++;
case SCANNER_STREAM_TYPE_VAR:
{
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
parser_emit_cbc_literal (context_p, CBC_CREATE_VAR, map_to);
break;
}
#if ENABLED (JERRY_ES2015)
case SCANNER_STREAM_TYPE_LET:
case SCANNER_STREAM_TYPE_CONST:
{
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
/* FIXME: introduce CBC_CREATE_LET / CBC_CREATE_CONST. */
parser_emit_cbc_literal (context_p, CBC_CREATE_VAR, map_to);
break;
}
case SCANNER_STREAM_TYPE_VAR_FUNC:
{
if (context_p->status_flags & PARSER_INSIDE_BLOCK)
{
func_init_opcode = CBC_CREATE_VAR_FUNC;
}
break;
}
#endif /* ENABLED (JERRY_ES2015) */
case SCANNER_STREAM_TYPE_ARG:
{
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
parser_emit_cbc_literal_value (context_p,
CBC_INIT_LOCAL,
(uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top),
map_to);
/* FALLTHRU */
}
case SCANNER_STREAM_TYPE_ARG_FUNC:
{
if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
{
scope_stack_reg_top++;
}
}
}
}
}
scope_stack_p++;
literal.char_p += data_p[1];
data_p += length;
if (type != SCANNER_STREAM_TYPE_ARG_FUNC && type != SCANNER_STREAM_TYPE_FUNC)
if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type))
{
continue;
}
@@ -1188,7 +1699,7 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
parser_emit_cbc_literal_value (context_p, CBC_INIT_LOCAL, context_p->literal_count, map_to);
parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to);
scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC;
scope_stack_p->map_to = context_p->literal_count;
@@ -1222,6 +1733,13 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
context_p->scope_stack_reg_top = (uint16_t) scope_stack_reg_top;
#if ENABLED (JERRY_ES2015)
if (info_type == SCANNER_TYPE_FUNCTION)
{
context_p->scope_stack_global_end = context_p->scope_stack_top;
}
#endif /* ENABLED (JERRY_ES2015) */
if (context_p->register_count < scope_stack_reg_top)
{
context_p->register_count = (uint16_t) scope_stack_reg_top;
+210 -11
View File
@@ -72,6 +72,10 @@ typedef enum
SCAN_STACK_WHILE_EXPRESSION, /**< expression part of "while" iterator */
SCAN_STACK_PAREN_EXPRESSION, /**< expression in brackets */
SCAN_STACK_STATEMENT_WITH_EXPR, /**< statement which starts with expression enclosed in brackets */
#if ENABLED (JERRY_ES2015)
SCAN_STACK_LET, /**< let statement */
SCAN_STACK_CONST, /**< const statement */
#endif /* ENABLED (JERRY_ES2015) */
/* The SCANNER_IS_FOR_START macro needs to be updated when the following constants are reordered. */
SCAN_STACK_VAR, /**< var statement */
SCAN_STACK_FOR_VAR_START, /**< start of "for" iterator with var statement */
@@ -504,6 +508,10 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
return SCAN_KEEP_TOKEN;
}
case SCAN_STACK_VAR:
#if ENABLED (JERRY_ES2015)
case SCAN_STACK_LET:
case SCAN_STACK_CONST:
#endif /* ENABLED (JERRY_ES2015) */
case SCAN_STACK_FOR_VAR_START:
{
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
@@ -628,6 +636,10 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
return SCAN_NEXT_TOKEN;
}
case SCAN_STACK_VAR:
#if ENABLED (JERRY_ES2015)
case SCAN_STACK_LET:
case SCAN_STACK_CONST:
#endif /* ENABLED (JERRY_ES2015) */
{
parser_stack_pop_uint8 (context_p);
return SCAN_KEEP_TOKEN;
@@ -752,6 +764,12 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
break;
}
#if ENABLED (JERRY_ES2015)
scanner_literal_pool_t *literal_pool_p;
literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_BLOCK);
literal_pool_p->source_p = context_p->source_p - 1;
#endif /* ENABLED (JERRY_ES2015) */
parser_stack_pop_uint8 (context_p);
scanner_switch_statement_t switch_statement = scanner_context_p->active_switch_statement;
@@ -966,6 +984,14 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
}
case LEXER_LEFT_BRACE:
{
#if ENABLED (JERRY_ES2015)
scanner_literal_pool_t *literal_pool_p;
literal_pool_p = scanner_push_literal_pool (context_p,
scanner_context_p,
SCANNER_LITERAL_POOL_BLOCK);
literal_pool_p->source_p = context_p->source_p;
#endif /* ENABLED (JERRY_ES2015) */
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
return SCAN_NEXT_TOKEN;
@@ -985,6 +1011,14 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
#if ENABLED (JERRY_ES2015)
scanner_literal_pool_t *literal_pool_p;
literal_pool_p = scanner_push_literal_pool (context_p,
scanner_context_p,
SCANNER_LITERAL_POOL_BLOCK);
literal_pool_p->source_p = context_p->source_p;
#endif /* ENABLED (JERRY_ES2015) */
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
parser_stack_push_uint8 (context_p, SCAN_STACK_TRY_STATEMENT);
return SCAN_NEXT_TOKEN;
@@ -1081,6 +1115,20 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
parser_stack_push_uint8 (context_p, SCAN_STACK_VAR);
return SCAN_NEXT_TOKEN;
}
#if ENABLED (JERRY_ES2015)
case LEXER_KEYW_LET:
{
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
parser_stack_push_uint8 (context_p, SCAN_STACK_LET);
return SCAN_NEXT_TOKEN;
}
case LEXER_KEYW_CONST:
{
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
parser_stack_push_uint8 (context_p, SCAN_STACK_CONST);
return SCAN_NEXT_TOKEN;
}
#endif /* ENABLED (JERRY_ES2015) */
case LEXER_KEYW_THROW:
{
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
@@ -1164,7 +1212,18 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
}
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
#if ENABLED (JERRY_ES2015)
if (location_p->type & SCANNER_LITERAL_IS_LET_OR_CONST
&& !(location_p->type & SCANNER_LITERAL_IS_FUNC))
{
scanner_raise_redeclaration_error (context_p);
}
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
#else
location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
#endif /* ENABLED (JERRY_ES2015) */
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
@@ -1182,8 +1241,22 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR;
lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
if (literal_p->type & (SCANNER_LITERAL_IS_ARG
| SCANNER_LITERAL_IS_LOCAL
| SCANNER_LITERAL_IS_VAR
| SCANNER_LITERAL_IS_LET_OR_CONST))
{
scanner_raise_redeclaration_error (context_p);
}
if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
{
literal_p->type = (uint8_t) (literal_p->type & ~SCANNER_LITERAL_IS_FUNC);
}
literal_p->type |= SCANNER_LITERAL_IS_LET;
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT);
@@ -1339,7 +1412,17 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
#if ENABLED (JERRY_ES2015)
if (location_p->type & SCANNER_LITERAL_IS_LET_OR_CONST
&& !(location_p->type & SCANNER_LITERAL_IS_FUNC))
{
scanner_raise_redeclaration_error (context_p);
}
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
#else /* !ENABLED (JERRY_ES2015) */
location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
#endif /* ENABLED (JERRY_ES2015) */
lexer_next_token (context_p);
}
@@ -1349,7 +1432,11 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
location_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p,
&lexer_default_literal);
#if ENABLED (JERRY_ES2015)
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
#else /* !ENABLED (JERRY_ES2015) */
location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
#endif /* ENABLED (JERRY_ES2015) */
}
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
@@ -1478,6 +1565,26 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
return SCAN_NEXT_TOKEN;
}
#if ENABLED (JERRY_ES2015)
if (context_p->token.type == LEXER_KEYW_CLASS)
{
/* FIXME: classes should be let declarations. */
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT);
lexer_next_token (context_p);
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
{
scanner_raise_error (context_p);
}
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR;
return SCAN_NEXT_TOKEN;
}
#endif /* ENABLED (JERRY_ES2015) */
scanner_context_p->mode = SCAN_MODE_STATEMENT;
return SCAN_KEEP_TOKEN;
}
@@ -1566,10 +1673,17 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
break;
}
#if ENABLED (JERRY_ES2015)
if (context_p->stack_top_uint8 != SCAN_STACK_CLASS_STATEMENT)
{
scanner_pop_literal_pool (context_p, scanner_context_p);
}
#else /* !ENABLED (JERRY_ES2015) */
if (context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_STATEMENT)
{
scanner_pop_literal_pool (context_p, scanner_context_p);
}
#endif /* ENABLED (JERRY_ES2015) */
terminator_found = true;
parser_stack_pop_uint8 (context_p);
@@ -1640,6 +1754,10 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
scanner_context_p->active_switch_statement = switch_statement;
#if ENABLED (JERRY_ES2015)
scanner_pop_literal_pool (context_p, scanner_context_p);
#endif /* ENABLED (JERRY_ES2015) */
terminator_found = true;
lexer_next_token (context_p);
continue;
@@ -1712,10 +1830,14 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
parser_stack_pop_uint8 (context_p);
lexer_next_token (context_p);
#if ENABLED (JERRY_ES2015)
scanner_pop_literal_pool (context_p, scanner_context_p);
#else /* !ENABLED (JERRY_ES2015) */
if (stack_top == SCAN_STACK_CATCH_STATEMENT)
{
scanner_pop_literal_pool (context_p, scanner_context_p);
}
#endif /* ENABLED (JERRY_ES2015) */
/* A finally statement is optional after a try or catch statement. */
if (context_p->token.type == LEXER_KEYW_FINALLY)
@@ -1727,6 +1849,14 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
#if ENABLED (JERRY_ES2015)
scanner_literal_pool_t *literal_pool_p;
literal_pool_p = scanner_push_literal_pool (context_p,
scanner_context_p,
SCANNER_LITERAL_POOL_BLOCK);
literal_pool_p->source_p = context_p->source_p;
#endif /* ENABLED (JERRY_ES2015) */
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
return SCAN_NEXT_TOKEN;
@@ -1839,9 +1969,14 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
context_p->source_p = source_p;
context_p->source_end_p = source_end_p;
#if ENABLED (JERRY_ES2015)
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS;
#else /* !ENABLED (JERRY_DEBUGGER) */
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS | SCANNER_LITERAL_POOL_NO_REG;
#endif /* ENABLED (JERRY_DEBUGGER) */
scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, &scanner_context, status_flags);
literal_pool_p->source_p = source_p;
literal_pool_p->source_p = source_p - 1;
scanner_context.mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT);
@@ -2011,12 +2146,45 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
lexer_lit_location_t *location_p = scanner_add_literal (context_p, &scanner_context);
location_p->type |= SCANNER_LITERAL_IS_VAR;
lexer_lit_location_t *literal_p = scanner_add_literal (context_p, &scanner_context);
#if ENABLED (JERRY_ES2015)
if (stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_CONST)
{
if (literal_p->type & (SCANNER_LITERAL_IS_ARG
| SCANNER_LITERAL_IS_LOCAL
| SCANNER_LITERAL_IS_VAR
| SCANNER_LITERAL_IS_LET_OR_CONST))
{
scanner_raise_redeclaration_error (context_p);
}
if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
{
literal_p->type = (uint8_t) (literal_p->type & ~SCANNER_LITERAL_IS_FUNC);
}
if (stack_top == SCAN_STACK_LET)
{
literal_p->type |= SCANNER_LITERAL_IS_LET;
}
else
{
literal_p->type |= SCANNER_LITERAL_IS_CONST;
}
}
else if (!(literal_p->type & SCANNER_LITERAL_IS_VAR))
{
scanner_detect_invalid_var (context_p, &scanner_context, literal_p);
literal_p->type |= SCANNER_LITERAL_IS_VAR;
}
#else /* !ENABLED (JERRY_ES2015) */
literal_p->type |= SCANNER_LITERAL_IS_VAR;
#endif /* ENABLED (JERRY_ES2015) */
if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
{
location_p->type |= SCANNER_LITERAL_NO_REG;
literal_p->type |= SCANNER_LITERAL_NO_REG;
}
lexer_next_token (context_p);
@@ -2048,7 +2216,11 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
continue;
}
#if ENABLED (JERRY_ES2015)
JERRY_ASSERT (stack_top == SCAN_STACK_VAR || stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_CONST);
#else /* !ENABLED (JERRY_ES2015) */
JERRY_ASSERT (stack_top == SCAN_STACK_VAR);
#endif /* ENABLED (JERRY_ES2015) */
scanner_context.mode = SCAN_MODE_STATEMENT_END;
parser_stack_pop_uint8 (context_p);
@@ -2275,6 +2447,14 @@ scan_completed:
scanner_raise_error (context_p);
}
#if ENABLED (JERRY_ES2015)
if (arg_list_p == NULL)
{
scanner_construct_global_block (context_p, &scanner_context);
scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_NO_REG;
}
#endif /* ENABLED (JERRY_ES2015) */
scanner_pop_literal_pool (context_p, &scanner_context);
#ifndef JERRY_NDEBUG
@@ -2364,6 +2544,23 @@ scan_completed:
{
switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
{
case SCANNER_STREAM_TYPE_VAR:
{
JERRY_DEBUG_MSG (" VAR ");
break;
}
#if ENABLED (JERRY_ES2015)
case SCANNER_STREAM_TYPE_LET:
{
JERRY_DEBUG_MSG (" LET ");
break;
}
case SCANNER_STREAM_TYPE_CONST:
{
JERRY_DEBUG_MSG (" CONST ");
break;
}
#endif /* ENABLED (JERRY_ES2015) */
case SCANNER_STREAM_TYPE_ARG:
{
JERRY_DEBUG_MSG (" ARG ");
@@ -2374,16 +2571,18 @@ scan_completed:
JERRY_DEBUG_MSG (" ARG_FUNC ");
break;
}
case SCANNER_STREAM_TYPE_VAR:
{
JERRY_DEBUG_MSG (" VAR ");
break;
}
case SCANNER_STREAM_TYPE_FUNC:
{
JERRY_DEBUG_MSG (" FUNC ");
break;
}
#if ENABLED (JERRY_ES2015)
case SCANNER_STREAM_TYPE_VAR_FUNC:
{
JERRY_DEBUG_MSG (" VAR_FUNC ");
break;
}
#endif /* ENABLED (JERRY_ES2015) */
default:
{
JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE);
+20 -3
View File
@@ -44,6 +44,9 @@ typedef enum
#endif /* ENABLED (JERRY_ES2015) */
SCANNER_TYPE_SWITCH, /**< switch statement */
SCANNER_TYPE_CASE, /**< case statement */
#if ENABLED (JERRY_ES2015)
SCANNER_TYPE_ERR_REDECLARED, /**< syntax error: a variable is redeclared */
#endif /* ENABLED (JERRY_ES2015) */
} scanner_info_type_t;
/**
@@ -127,6 +130,7 @@ typedef enum
SCANNER_STREAM_UINT16_DIFF = (1 << 7), /**< relative distance is between -256 and 65535 */
SCANNER_STREAM_HAS_ESCAPE = (1 << 6), /**< literal has escape */
SCANNER_STREAM_NO_REG = (1 << 5), /**< identifier cannot be stored in register */
/* Update SCANNER_STREAM_TYPE_MASK macro if more bits are added. */
} scanner_compressed_stream_flags_t;
/**
@@ -136,10 +140,18 @@ typedef enum
{
SCANNER_STREAM_TYPE_END, /**< end of scanner data */
SCANNER_STREAM_TYPE_HOLE, /**< no name is assigned to this argument */
SCANNER_STREAM_TYPE_ARG, /**< argument declaration */
SCANNER_STREAM_TYPE_ARG_FUNC, /**< argument declaration which is later initialized with a function */
SCANNER_STREAM_TYPE_VAR, /**< var declaration */
SCANNER_STREAM_TYPE_FUNC, /**< function declaration */
#if ENABLED (JERRY_ES2015)
SCANNER_STREAM_TYPE_LET, /**< let declaration */
SCANNER_STREAM_TYPE_CONST, /**< const declaration */
#endif /* ENABLED (JERRY_ES2015) */
SCANNER_STREAM_TYPE_ARG, /**< argument declaration */
/* Function types should be at the end. See the SCANNER_STREAM_TYPE_IS_FUNCTION macro. */
SCANNER_STREAM_TYPE_ARG_FUNC, /**< argument declaration which is later initialized with a function */
SCANNER_STREAM_TYPE_FUNC, /**< local function declaration */
#if ENABLED (JERRY_ES2015)
SCANNER_STREAM_TYPE_VAR_FUNC, /**< var function declaration */
#endif /* ENABLED (JERRY_ES2015) */
} scanner_compressed_stream_types_t;
/**
@@ -147,6 +159,11 @@ typedef enum
*/
#define SCANNER_STREAM_TYPE_MASK 0xf
/**
* Mask for decoding the type from the compressed stream.
*/
#define SCANNER_STREAM_TYPE_IS_FUNCTION(type) ((type) >= SCANNER_STREAM_TYPE_ARG_FUNC)
/**
* Constants for u8_arg flags in scanner_function_info_t.
*/