mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Introduce parser scope types, add scope flags, indicating whether scope contains a function declaration, a 'try' statement, 'with' statement or 'delete' operator.
JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
This commit is contained in:
parent
c3d8cfd73c
commit
91aecc3bd0
@ -91,10 +91,12 @@ ecma_op_eval_chars_buffer (const jerry_api_char_t *code_p, /**< code characters
|
||||
|
||||
bool is_strict_call = (is_direct && is_called_from_strict_mode_code);
|
||||
|
||||
bool code_contains_functions;
|
||||
parse_status = parser_parse_eval (code_p,
|
||||
code_buffer_size,
|
||||
is_strict_call,
|
||||
&instrs_p);
|
||||
&instrs_p,
|
||||
&code_contains_functions);
|
||||
|
||||
if (parse_status == JSP_STATUS_SYNTAX_ERROR)
|
||||
{
|
||||
@ -158,7 +160,7 @@ ecma_op_eval_chars_buffer (const jerry_api_char_t *code_p, /**< code characters
|
||||
JERRY_ASSERT (ecma_is_completion_value_throw (completion));
|
||||
}
|
||||
|
||||
if (!parser_is_code_contains_functions ())
|
||||
if (!code_contains_functions)
|
||||
{
|
||||
serializer_remove_instructions (instrs_p);
|
||||
}
|
||||
|
||||
@ -50,10 +50,6 @@ static token tok;
|
||||
static bool inside_eval = false;
|
||||
static bool inside_function = false;
|
||||
static bool parser_show_instrs = false;
|
||||
/**
|
||||
* flag, indicating that code contains function declarations or function expressions
|
||||
*/
|
||||
static bool code_contains_functions = false;
|
||||
|
||||
enum
|
||||
{
|
||||
@ -383,14 +379,14 @@ parse_property_assignment (void)
|
||||
return;
|
||||
}
|
||||
|
||||
code_contains_functions = true;
|
||||
|
||||
STACK_DECLARE_USAGE (scopes);
|
||||
|
||||
const operand name = parse_property_name ();
|
||||
jsp_early_error_add_prop_name (name, is_setter ? PROP_SET : PROP_GET);
|
||||
|
||||
STACK_PUSH (scopes, scopes_tree_init (NULL));
|
||||
scopes_tree_set_contains_functions (STACK_TOP (scopes));
|
||||
|
||||
STACK_PUSH (scopes, scopes_tree_init (NULL, SCOPE_TYPE_FUNCTION));
|
||||
serializer_set_scope (STACK_TOP (scopes));
|
||||
scopes_tree_set_strict_mode (STACK_TOP (scopes), scopes_tree_strict_mode (STACK_HEAD (scopes, 2)));
|
||||
lexer_set_strict_mode (scopes_tree_strict_mode (STACK_TOP (scopes)));
|
||||
@ -652,8 +648,6 @@ parse_function_declaration (void)
|
||||
{
|
||||
STACK_DECLARE_USAGE (scopes);
|
||||
|
||||
code_contains_functions = true;
|
||||
|
||||
assert_keyword (KW_FUNCTION);
|
||||
|
||||
jsp_label_t *masked_label_set_p = jsp_label_mask_set ();
|
||||
@ -664,7 +658,10 @@ parse_function_declaration (void)
|
||||
jsp_early_error_check_for_eval_and_arguments_in_strict_mode (name, is_strict_mode (), tok.loc);
|
||||
|
||||
skip_newlines ();
|
||||
STACK_PUSH (scopes, scopes_tree_init (STACK_TOP (scopes)));
|
||||
|
||||
scopes_tree_set_contains_functions (STACK_TOP (scopes));
|
||||
|
||||
STACK_PUSH (scopes, scopes_tree_init (STACK_TOP (scopes), SCOPE_TYPE_FUNCTION));
|
||||
serializer_set_scope (STACK_TOP (scopes));
|
||||
scopes_tree_set_strict_mode (STACK_TOP (scopes), scopes_tree_strict_mode (STACK_HEAD (scopes, 2)));
|
||||
lexer_set_strict_mode (scopes_tree_strict_mode (STACK_TOP (scopes)));
|
||||
@ -709,13 +706,13 @@ parse_function_expression (void)
|
||||
STACK_DECLARE_USAGE (scopes);
|
||||
assert_keyword (KW_FUNCTION);
|
||||
|
||||
code_contains_functions = true;
|
||||
|
||||
operand res;
|
||||
|
||||
jsp_early_error_start_checking_of_vargs ();
|
||||
|
||||
STACK_PUSH (scopes, scopes_tree_init (NULL));
|
||||
scopes_tree_set_contains_functions (STACK_TOP (scopes));
|
||||
|
||||
STACK_PUSH (scopes, scopes_tree_init (NULL, SCOPE_TYPE_FUNCTION));
|
||||
serializer_set_scope (STACK_TOP (scopes));
|
||||
scopes_tree_set_strict_mode (STACK_TOP (scopes), scopes_tree_strict_mode (STACK_HEAD (scopes, 2)));
|
||||
lexer_set_strict_mode (scopes_tree_strict_mode (STACK_TOP (scopes)));
|
||||
@ -1191,6 +1188,8 @@ parse_unary_expression (operand *this_arg_gl, operand *prop_gl)
|
||||
{
|
||||
if (is_keyword (KW_DELETE))
|
||||
{
|
||||
scopes_tree_set_contains_delete (STACK_TOP (scopes));
|
||||
|
||||
skip_newlines ();
|
||||
expr = parse_unary_expression (NULL, NULL);
|
||||
expr = dump_delete_res (expr, is_strict_mode (), tok.loc);
|
||||
@ -2361,6 +2360,8 @@ parse_with_statement (void)
|
||||
}
|
||||
const operand expr = parse_expression_inside_parens ();
|
||||
|
||||
scopes_tree_set_contains_with (STACK_TOP (scopes));
|
||||
|
||||
bool is_raised = jsp_label_raise_nested_jumpable_border ();
|
||||
|
||||
vm_instr_counter_t with_begin_oc = dump_with_for_rewrite (expr);
|
||||
@ -2542,6 +2543,8 @@ parse_try_statement (void)
|
||||
{
|
||||
assert_keyword (KW_TRY);
|
||||
|
||||
scopes_tree_set_contains_try (STACK_TOP (scopes));
|
||||
|
||||
bool is_raised = jsp_label_raise_nested_jumpable_border ();
|
||||
|
||||
dump_try_for_rewrite ();
|
||||
@ -3030,18 +3033,27 @@ parse_source_element_list (bool is_global) /**< flag, indicating that we parsing
|
||||
static jsp_status_t
|
||||
parser_parse_program (const jerry_api_char_t *source_p, /**< source code buffer */
|
||||
size_t source_size, /**< source code size in bytes */
|
||||
bool in_function, /**< flag indicating if we are parsing body of a function */
|
||||
bool in_dyn_constructed_function, /**< flag indicating if we are parsing body of a function,
|
||||
* constructed using 'new Function (...)'-like expression */
|
||||
bool in_eval, /**< flag indicating if we are parsing body of eval code */
|
||||
bool is_strict, /**< flag, indicating whether current code
|
||||
* inherited strict mode from code of an outer scope */
|
||||
const vm_instr_t **out_instrs_p) /**< out: generated byte-code array
|
||||
const vm_instr_t **out_instrs_p, /**< out: generated byte-code array
|
||||
* (in case there were no syntax errors) */
|
||||
bool *out_contains_functions_p) /**< out: optional (can be NULL, if the output is not needed)
|
||||
* flag, indicating whether the compiled byte-code
|
||||
* contains a function declaration / expression */
|
||||
{
|
||||
JERRY_ASSERT (out_instrs_p != NULL);
|
||||
|
||||
inside_function = in_function;
|
||||
JERRY_ASSERT (!(in_dyn_constructed_function && in_eval));
|
||||
|
||||
inside_function = in_dyn_constructed_function;
|
||||
inside_eval = in_eval;
|
||||
code_contains_functions = false;
|
||||
|
||||
scope_type_t scope_type = (in_dyn_constructed_function ? SCOPE_TYPE_FUNCTION
|
||||
: (in_eval ? SCOPE_TYPE_EVAL
|
||||
: SCOPE_TYPE_GLOBAL));
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
volatile bool is_parse_finished = false;
|
||||
@ -3057,7 +3069,7 @@ parser_parse_program (const jerry_api_char_t *source_p, /**< source code buffer
|
||||
jsp_early_error_init ();
|
||||
|
||||
STACK_INIT (scopes);
|
||||
STACK_PUSH (scopes, scopes_tree_init (NULL));
|
||||
STACK_PUSH (scopes, scopes_tree_init (NULL, scope_type));
|
||||
serializer_set_scope (STACK_TOP (scopes));
|
||||
scopes_tree_set_strict_mode (STACK_TOP (scopes), is_strict);
|
||||
|
||||
@ -3080,7 +3092,7 @@ parser_parse_program (const jerry_api_char_t *source_p, /**< source code buffer
|
||||
skip_newlines ();
|
||||
JERRY_ASSERT (token_is (TOK_EOF));
|
||||
|
||||
if (in_function)
|
||||
if (in_dyn_constructed_function)
|
||||
{
|
||||
dump_ret ();
|
||||
}
|
||||
@ -3103,6 +3115,13 @@ parser_parse_program (const jerry_api_char_t *source_p, /**< source code buffer
|
||||
|
||||
dumper_free ();
|
||||
|
||||
if (out_contains_functions_p != NULL)
|
||||
{
|
||||
scopes_tree scope = STACK_TOP (scopes);
|
||||
|
||||
*out_contains_functions_p = scope->contains_functions;
|
||||
}
|
||||
|
||||
serializer_set_scope (NULL);
|
||||
scopes_tree_free (STACK_TOP (scopes));
|
||||
STACK_DROP (scopes, 1);
|
||||
@ -3155,7 +3174,7 @@ parser_parse_script (const jerry_api_char_t *source, /**< source script */
|
||||
const vm_instr_t **out_instrs_p) /**< out: generated byte-code array
|
||||
* (in case there were no syntax errors) */
|
||||
{
|
||||
return parser_parse_program (source, source_size, false, false, false, out_instrs_p);
|
||||
return parser_parse_program (source, source_size, false, false, false, out_instrs_p, NULL);
|
||||
} /* parser_parse_script */
|
||||
|
||||
/**
|
||||
@ -3169,10 +3188,14 @@ parser_parse_eval (const jerry_api_char_t *source, /**< string passed to eval()
|
||||
size_t source_size, /**< string size in bytes */
|
||||
bool is_strict, /**< flag, indicating whether eval is called
|
||||
* from strict code in direct mode */
|
||||
const vm_instr_t **out_instrs_p) /**< out: generated byte-code array
|
||||
const vm_instr_t **out_instrs_p, /**< out: generated byte-code array
|
||||
* (in case there were no syntax errors) */
|
||||
bool *out_contains_functions_p) /**< out: flag, indicating whether the compiled byte-code
|
||||
* contains a function declaration / expression */
|
||||
{
|
||||
return parser_parse_program (source, source_size, false, true, is_strict, out_instrs_p);
|
||||
JERRY_ASSERT (out_contains_functions_p != NULL);
|
||||
|
||||
return parser_parse_program (source, source_size, false, true, is_strict, out_instrs_p, out_contains_functions_p);
|
||||
} /* parser_parse_eval */
|
||||
|
||||
/**
|
||||
@ -3205,20 +3228,10 @@ parser_parse_new_function (const jerry_api_char_t **params, /**< array of argume
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
out_instrs_p);
|
||||
out_instrs_p,
|
||||
NULL);
|
||||
} /* parser_parse_new_function */
|
||||
|
||||
/**
|
||||
* Indicates whether code contains functions
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool
|
||||
parser_is_code_contains_functions ()
|
||||
{
|
||||
return code_contains_functions;
|
||||
} /* parser_is_code_contains_functions */
|
||||
|
||||
/**
|
||||
* Tell parser whether to dump bytecode
|
||||
*/
|
||||
|
||||
@ -30,8 +30,7 @@ typedef enum
|
||||
|
||||
void parser_set_show_instrs (bool);
|
||||
jsp_status_t parser_parse_script (const jerry_api_char_t *, size_t, const vm_instr_t **);
|
||||
jsp_status_t parser_parse_eval (const jerry_api_char_t *, size_t, bool, const vm_instr_t **);
|
||||
jsp_status_t parser_parse_eval (const jerry_api_char_t *, size_t, bool, const vm_instr_t **, bool *);
|
||||
jsp_status_t parser_parse_new_function (const jerry_api_char_t **, const size_t *, size_t, const vm_instr_t **);
|
||||
bool parser_is_code_contains_functions ();
|
||||
|
||||
#endif /* PARSER_H */
|
||||
|
||||
@ -743,6 +743,46 @@ scopes_tree_set_eval_used (scopes_tree tree) /**< scope */
|
||||
tree->ref_eval = true;
|
||||
} /* scopes_tree_set_eval_used */
|
||||
|
||||
/**
|
||||
* Set up a flag, indicating that 'with' statement is contained in a scope
|
||||
*/
|
||||
void
|
||||
scopes_tree_set_contains_with (scopes_tree tree) /**< scope */
|
||||
{
|
||||
assert_tree (tree);
|
||||
tree->contains_with = true;
|
||||
} /* scopes_tree_set_contains_with */
|
||||
|
||||
/**
|
||||
* Set up a flag, indicating that 'try' statement is contained in a scope
|
||||
*/
|
||||
void
|
||||
scopes_tree_set_contains_try (scopes_tree tree) /**< scope */
|
||||
{
|
||||
assert_tree (tree);
|
||||
tree->contains_try = true;
|
||||
} /* scopes_tree_set_contains_try */
|
||||
|
||||
/**
|
||||
* Set up a flag, indicating that 'delete' operator is contained in a scope
|
||||
*/
|
||||
void
|
||||
scopes_tree_set_contains_delete (scopes_tree tree) /**< scope */
|
||||
{
|
||||
assert_tree (tree);
|
||||
tree->contains_delete = true;
|
||||
} /* scopes_tree_set_contains_delete */
|
||||
|
||||
/**
|
||||
* Set up a flag, indicating that there is a function declaration / expression inside a scope
|
||||
*/
|
||||
void
|
||||
scopes_tree_set_contains_functions (scopes_tree tree) /**< scope */
|
||||
{
|
||||
assert_tree (tree);
|
||||
tree->contains_functions = true;
|
||||
} /* scopes_tree_set_contains_functions */
|
||||
|
||||
bool
|
||||
scopes_tree_strict_mode (scopes_tree tree)
|
||||
{
|
||||
@ -756,7 +796,8 @@ scopes_tree_strict_mode (scopes_tree tree)
|
||||
* @return initialized scope
|
||||
*/
|
||||
scopes_tree
|
||||
scopes_tree_init (scopes_tree parent) /**< parent scope */
|
||||
scopes_tree_init (scopes_tree parent, /**< parent scope */
|
||||
scope_type_t type) /**< scope type */
|
||||
{
|
||||
scopes_tree tree = (scopes_tree) jsp_mm_alloc (sizeof (scopes_tree_int));
|
||||
memset (tree, 0, sizeof (scopes_tree_int));
|
||||
@ -775,9 +816,14 @@ scopes_tree_init (scopes_tree parent) /**< parent scope */
|
||||
parent->t.children_num++;
|
||||
}
|
||||
tree->instrs_count = 0;
|
||||
tree->type = type;
|
||||
tree->strict_mode = false;
|
||||
tree->ref_eval = false;
|
||||
tree->ref_arguments = false;
|
||||
tree->ref_eval = false;
|
||||
tree->contains_with = false;
|
||||
tree->contains_try = false;
|
||||
tree->contains_delete = false;
|
||||
tree->contains_functions = false;
|
||||
tree->instrs = linked_list_init (sizeof (op_meta));
|
||||
tree->var_decls_cout = 0;
|
||||
tree->var_decls = linked_list_init (sizeof (op_meta));
|
||||
|
||||
@ -39,6 +39,16 @@ typedef struct tree_header
|
||||
uint8_t children_num;
|
||||
} tree_header;
|
||||
|
||||
/**
|
||||
* Scope type
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SCOPE_TYPE_GLOBAL, /**< the Global code scope */
|
||||
SCOPE_TYPE_FUNCTION, /**< a function code scope */
|
||||
SCOPE_TYPE_EVAL /**< an eval code scope */
|
||||
} scope_type_t;
|
||||
|
||||
/**
|
||||
* Structure for holding scope information during parsing
|
||||
*/
|
||||
@ -49,14 +59,24 @@ typedef struct
|
||||
vm_instr_counter_t instrs_count; /**< count of instructions */
|
||||
linked_list var_decls; /**< instructions for variable declarations */
|
||||
uint8_t var_decls_cout; /**< number of instructions for variable declarations */
|
||||
scope_type_t type : 2; /**< scope type */
|
||||
bool strict_mode: 1; /**< flag, indicating that scope's code should be executed in strict mode */
|
||||
bool ref_arguments: 1; /**< flag, indicating that "arguments" variable is used inside the scope */
|
||||
bool ref_eval: 1; /**< flag, indicating that "eval" is used inside the scope */
|
||||
bool ref_arguments: 1; /**< flag, indicating that "arguments" variable is used inside the scope
|
||||
* (not depends on subscopes) */
|
||||
bool ref_eval: 1; /**< flag, indicating that "eval" is used inside the scope
|
||||
* (not depends on subscopes) */
|
||||
bool contains_with: 1; /**< flag, indicationg whether 'with' statement is contained in the scope
|
||||
* (not depends on subscopes) */
|
||||
bool contains_try: 1; /**< flag, indicationg whether 'try' statement is contained in the scope
|
||||
* (not depends on subscopes) */
|
||||
bool contains_delete: 1; /**< flag, indicationg whether 'delete' operator is contained in the scope
|
||||
* (not depends on subscopes) */
|
||||
bool contains_functions: 1; /**< flag, indicating that the scope contains a function declaration / expression */
|
||||
} scopes_tree_int;
|
||||
|
||||
typedef scopes_tree_int * scopes_tree;
|
||||
|
||||
scopes_tree scopes_tree_init (scopes_tree);
|
||||
scopes_tree scopes_tree_init (scopes_tree, scope_type_t);
|
||||
void scopes_tree_free (scopes_tree);
|
||||
vm_instr_counter_t scopes_tree_instrs_num (scopes_tree);
|
||||
vm_instr_counter_t scopes_tree_var_decls_num (scopes_tree);
|
||||
@ -72,6 +92,10 @@ vm_instr_t *scopes_tree_raw_data (scopes_tree, uint8_t *, size_t, lit_id_hash_ta
|
||||
void scopes_tree_set_strict_mode (scopes_tree, bool);
|
||||
void scopes_tree_set_arguments_used (scopes_tree);
|
||||
void scopes_tree_set_eval_used (scopes_tree);
|
||||
void scopes_tree_set_contains_with (scopes_tree);
|
||||
void scopes_tree_set_contains_try (scopes_tree);
|
||||
void scopes_tree_set_contains_delete (scopes_tree);
|
||||
void scopes_tree_set_contains_functions (scopes_tree);
|
||||
bool scopes_tree_strict_mode (scopes_tree);
|
||||
|
||||
#endif /* SCOPES_TREE_H */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user