Add literals - replacements of strings and numbers in parser.
This commit is contained in:
+151
-147
@@ -46,21 +46,9 @@ static size_t strings_cache_used_size;
|
||||
|
||||
enum
|
||||
{
|
||||
strings_global_size
|
||||
literals_global_size
|
||||
};
|
||||
STATIC_STACK (strings, uint8_t, lp_string)
|
||||
|
||||
enum
|
||||
{
|
||||
numbers_global_size
|
||||
};
|
||||
STATIC_STACK (numbers, uint8_t, ecma_number_t)
|
||||
|
||||
enum
|
||||
{
|
||||
num_ids_global_size
|
||||
};
|
||||
STATIC_STACK (num_ids, uint8_t, idx_t)
|
||||
STATIC_STACK (literals, uint8_t, literal)
|
||||
|
||||
static bool
|
||||
is_empty (token tok)
|
||||
@@ -116,7 +104,7 @@ create_token (token_type type, uint8_t uid)
|
||||
return (token)
|
||||
{
|
||||
.type = type,
|
||||
.loc = current_locus (),
|
||||
.loc = current_locus () - (type == TOK_STRING ? 1 : 0),
|
||||
.uid = uid
|
||||
};
|
||||
}
|
||||
@@ -136,49 +124,74 @@ current_token_equals_to (const char *str)
|
||||
}
|
||||
|
||||
static bool
|
||||
current_token_equals_to_lp (lp_string str)
|
||||
current_token_equals_to_literal (literal lit)
|
||||
{
|
||||
if (str.length != (ecma_length_t) (buffer - token_start))
|
||||
if (lit.type == LIT_STR)
|
||||
{
|
||||
return false;
|
||||
if (lit.data.lp.length != (ecma_length_t) (buffer - token_start))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!__strncmp ((const char *) lit.data.lp.str, token_start, lit.data.lp.length))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!__strncmp ((const char *) str.str, token_start, str.length))
|
||||
else if (lit.type == LIT_MAGIC_STR)
|
||||
{
|
||||
return true;
|
||||
const char *str = (const char *) ecma_get_magic_string_zt (lit.data.magic_str_id);
|
||||
if (__strlen (str) != /* Fucking [-Werror=sign-compare] */ (size_t) (buffer - token_start))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!__strncmp (str, token_start, __strlen (str)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static lp_string
|
||||
adjust_string_ptrs (lp_string lp, size_t diff)
|
||||
static literal
|
||||
adjust_string_ptrs (literal lit, size_t diff)
|
||||
{
|
||||
return (lp_string)
|
||||
if (lit.type != LIT_STR)
|
||||
{
|
||||
.length = lp.length,
|
||||
.str = lp.str + diff
|
||||
return lit;
|
||||
}
|
||||
return (literal)
|
||||
{
|
||||
.type = LIT_STR,
|
||||
.data.lp = (lp_string)
|
||||
{
|
||||
.length = lit.data.lp.length,
|
||||
.str = lit.data.lp.str + diff
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static lp_string
|
||||
static literal
|
||||
add_current_token_to_string_cache (void)
|
||||
{
|
||||
lp_string res;
|
||||
res.length = (ecma_length_t) (buffer - token_start);
|
||||
if (strings_cache_used_size + res.length * sizeof (ecma_char_t) >= strings_cache_size)
|
||||
const ecma_length_t length = (ecma_length_t) (buffer - token_start);
|
||||
if (strings_cache_used_size + length * sizeof (ecma_char_t) >= strings_cache_size)
|
||||
{
|
||||
strings_cache_size = mem_heap_recommend_allocation_size (strings_cache_used_size
|
||||
+ ((size_t) res.length + 1) * sizeof (ecma_char_t));
|
||||
+ ((size_t) length + 1) * sizeof (ecma_char_t));
|
||||
ecma_char_t *temp = (ecma_char_t *) mem_heap_alloc_block (strings_cache_size,
|
||||
MEM_HEAP_ALLOC_SHORT_TERM);
|
||||
__memcpy (temp, strings_cache, strings_cache_used_size);
|
||||
mem_heap_free_block ((uint8_t *) strings_cache);
|
||||
STACK_ITERATE_VARG_SET (strings, adjust_string_ptrs, 0, (size_t) (temp - strings_cache));
|
||||
STACK_ITERATE_VARG_SET (literals, adjust_string_ptrs, 0, (size_t) (temp - strings_cache));
|
||||
if (strings_cache)
|
||||
{
|
||||
mem_heap_free_block ((uint8_t *) strings_cache);
|
||||
}
|
||||
strings_cache = temp;
|
||||
}
|
||||
__strncpy ((char *) (strings_cache + strings_cache_used_size), token_start, res.length);
|
||||
res.str = strings_cache + strings_cache_used_size;
|
||||
(strings_cache + strings_cache_used_size)[res.length] = '\0';
|
||||
strings_cache_used_size = (size_t) (((size_t) res.length + 1) * sizeof (ecma_char_t) + strings_cache_used_size);
|
||||
__strncpy ((char *) (strings_cache + strings_cache_used_size), token_start, length);
|
||||
(strings_cache + strings_cache_used_size)[length] = '\0';
|
||||
const literal res = create_literal_from_zt (strings_cache + strings_cache_used_size, length);
|
||||
strings_cache_used_size = (size_t) (((size_t) length + 1) * sizeof (ecma_char_t) + strings_cache_used_size);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -187,9 +200,11 @@ convert_current_token_to_token (token_type tt)
|
||||
{
|
||||
JERRY_ASSERT (token_start);
|
||||
|
||||
for (uint8_t i = 0; i < STACK_SIZE (strings); i++)
|
||||
for (uint8_t i = 0; i < STACK_SIZE (literals); i++)
|
||||
{
|
||||
if (current_token_equals_to_lp (STACK_ELEMENT (strings, i)))
|
||||
const literal lit = STACK_ELEMENT (literals, i);
|
||||
if ((lit.type == LIT_STR || lit.type == LIT_MAGIC_STR)
|
||||
&& current_token_equals_to_literal (lit))
|
||||
{
|
||||
if (tt == TOK_STRING)
|
||||
{
|
||||
@@ -208,11 +223,16 @@ convert_current_token_to_token (token_type tt)
|
||||
}
|
||||
}
|
||||
|
||||
const lp_string str = add_current_token_to_string_cache ();
|
||||
literal lit = create_literal_from_str (token_start, (ecma_length_t) (buffer - token_start));
|
||||
JERRY_ASSERT (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR);
|
||||
if (lit.type == LIT_STR)
|
||||
{
|
||||
lit = add_current_token_to_string_cache ();
|
||||
}
|
||||
|
||||
STACK_PUSH (strings, str);
|
||||
STACK_PUSH (literals, lit);
|
||||
|
||||
return create_token (tt, (idx_t) (STACK_SIZE (strings) - 1));
|
||||
return create_token (tt, (idx_t) (STACK_SIZE (literals) - 1));
|
||||
}
|
||||
|
||||
/* If TOKEN represents a keyword, return decoded keyword,
|
||||
@@ -235,11 +255,11 @@ decode_keyword (void)
|
||||
}
|
||||
if (current_token_equals_to ("class"))
|
||||
{
|
||||
PARSE_SORRY ("'class' is reseved keyword and not supported yet", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_CLASS);
|
||||
}
|
||||
if (current_token_equals_to ("const"))
|
||||
{
|
||||
PARSE_SORRY ("'const' is reseved keyword and not supported yet", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_CONST);
|
||||
}
|
||||
if (current_token_equals_to ("continue"))
|
||||
{
|
||||
@@ -267,15 +287,15 @@ decode_keyword (void)
|
||||
}
|
||||
if (current_token_equals_to ("enum"))
|
||||
{
|
||||
PARSE_SORRY ("'enum' is reseved keyword and not supported yet", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_ENUM);
|
||||
}
|
||||
if (current_token_equals_to ("export"))
|
||||
{
|
||||
PARSE_SORRY ("'export' is reseved keyword and not supported yet", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_EXPORT);
|
||||
}
|
||||
if (current_token_equals_to ("extends"))
|
||||
{
|
||||
PARSE_SORRY ("'extends' is reseved keyword and not supported yet", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_EXTENDS);
|
||||
}
|
||||
if (current_token_equals_to ("false"))
|
||||
{
|
||||
@@ -297,6 +317,10 @@ decode_keyword (void)
|
||||
{
|
||||
return create_token (TOK_KEYWORD, KW_IF);
|
||||
}
|
||||
if (current_token_equals_to ("in"))
|
||||
{
|
||||
return create_token (TOK_KEYWORD, KW_IN);
|
||||
}
|
||||
if (current_token_equals_to ("instanceof"))
|
||||
{
|
||||
return create_token (TOK_KEYWORD, KW_INSTANCEOF);
|
||||
@@ -305,26 +329,22 @@ decode_keyword (void)
|
||||
{
|
||||
if (parser_strict_mode ())
|
||||
{
|
||||
PARSE_ERROR ("'interface' is reseved keyword and not allowed in strict mode", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_INTERFACE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return convert_current_token_to_token (TOK_NAME);
|
||||
}
|
||||
}
|
||||
if (current_token_equals_to ("in"))
|
||||
{
|
||||
return create_token (TOK_KEYWORD, KW_IN);
|
||||
}
|
||||
if (current_token_equals_to ("import"))
|
||||
{
|
||||
PARSE_SORRY ("'import' is reseved keyword and not supported yet", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_IMPORT);
|
||||
}
|
||||
if (current_token_equals_to ("implements"))
|
||||
{
|
||||
if (parser_strict_mode ())
|
||||
{
|
||||
PARSE_ERROR ("'implements' is reseved keyword and not allowed in strict mode", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_IMPLEMENTS);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -335,7 +355,7 @@ decode_keyword (void)
|
||||
{
|
||||
if (parser_strict_mode ())
|
||||
{
|
||||
PARSE_ERROR ("'let' is reseved keyword and not allowed in strict mode", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_LET);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -354,7 +374,7 @@ decode_keyword (void)
|
||||
{
|
||||
if (parser_strict_mode ())
|
||||
{
|
||||
PARSE_ERROR ("'package' is reseved keyword and not allowed in strict mode", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_PACKAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -365,7 +385,7 @@ decode_keyword (void)
|
||||
{
|
||||
if (parser_strict_mode ())
|
||||
{
|
||||
PARSE_ERROR ("'private' is reseved keyword and not allowed in strict mode", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_PRIVATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -376,7 +396,7 @@ decode_keyword (void)
|
||||
{
|
||||
if (parser_strict_mode ())
|
||||
{
|
||||
PARSE_ERROR ("'protected' is reseved keyword and not allowed in strict mode", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_PROTECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -387,7 +407,7 @@ decode_keyword (void)
|
||||
{
|
||||
if (parser_strict_mode ())
|
||||
{
|
||||
PARSE_ERROR ("'public' is reseved keyword and not allowed in strict mode", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_PUBLIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -402,7 +422,7 @@ decode_keyword (void)
|
||||
{
|
||||
if (parser_strict_mode ())
|
||||
{
|
||||
PARSE_ERROR ("'static' is reseved keyword and not allowed in strict mode", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_STATIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -411,7 +431,7 @@ decode_keyword (void)
|
||||
}
|
||||
if (current_token_equals_to ("super"))
|
||||
{
|
||||
PARSE_SORRY ("'super' is reseved keyword and not supported yet", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_SUPER);
|
||||
}
|
||||
if (current_token_equals_to ("switch"))
|
||||
{
|
||||
@@ -457,7 +477,7 @@ decode_keyword (void)
|
||||
{
|
||||
if (parser_strict_mode ())
|
||||
{
|
||||
PARSE_ERROR ("'yield' is reseved keyword and not allowed in strict mode", current_locus ());
|
||||
return create_token (TOK_KEYWORD, KW_YIELD);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -470,81 +490,75 @@ decode_keyword (void)
|
||||
static token
|
||||
convert_seen_num_to_token (ecma_number_t num)
|
||||
{
|
||||
uint8_t num_id;
|
||||
|
||||
JERRY_ASSERT (STACK_SIZE (num_ids) == STACK_SIZE (numbers));
|
||||
for (uint8_t i = 0; i < STACK_SIZE (numbers); i++)
|
||||
for (uint8_t i = 0; i < STACK_SIZE (literals); i++)
|
||||
{
|
||||
if (STACK_ELEMENT (numbers, i) == num)
|
||||
const literal lit = STACK_ELEMENT (literals, i);
|
||||
if (lit.type != LIT_NUMBER)
|
||||
{
|
||||
return create_token (TOK_NUMBER, STACK_ELEMENT (num_ids, i));
|
||||
continue;
|
||||
}
|
||||
if (lit.data.num == num)
|
||||
{
|
||||
return create_token (TOK_NUMBER, i);
|
||||
}
|
||||
}
|
||||
|
||||
num_id = STACK_SIZE (num_ids);
|
||||
STACK_PUSH (num_ids, num_id);
|
||||
STACK_PUSH (numbers, num);
|
||||
STACK_PUSH (literals, create_literal_from_num (num));
|
||||
|
||||
return create_token (TOK_NUMBER, num_id);
|
||||
return create_token (TOK_NUMBER, (idx_t) (STACK_SIZE (literals) - 1));
|
||||
}
|
||||
|
||||
const lp_string *
|
||||
lexer_get_strings (void)
|
||||
const literal *
|
||||
lexer_get_literals (void)
|
||||
{
|
||||
lp_string *data = NULL;
|
||||
STACK_CONVERT_TO_RAW_DATA (strings, data);
|
||||
literal *data = NULL;
|
||||
STACK_CONVERT_TO_RAW_DATA (literals, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
lexer_get_strings_count (void)
|
||||
lexer_get_literals_count (void)
|
||||
{
|
||||
return STACK_SIZE (strings);
|
||||
return STACK_SIZE (literals);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
lexer_get_reserved_ids_count (void)
|
||||
idx_t
|
||||
lexer_lookup_literal_uid (literal lit)
|
||||
{
|
||||
return (uint8_t) (STACK_SIZE (strings) + STACK_SIZE (numbers));
|
||||
for (uint8_t i = 0; i < STACK_SIZE (literals); i++)
|
||||
{
|
||||
if (literal_equal_type (STACK_ELEMENT (literals, i), lit))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return INVALID_VALUE;
|
||||
}
|
||||
|
||||
lp_string
|
||||
lexer_get_string_by_id (uint8_t id)
|
||||
literal
|
||||
lexer_get_literal_by_id (uint8_t id)
|
||||
{
|
||||
JERRY_ASSERT (id < STACK_SIZE (strings));
|
||||
return STACK_ELEMENT (strings, id);
|
||||
JERRY_ASSERT (id < STACK_SIZE (literals));
|
||||
return STACK_ELEMENT (literals, id);
|
||||
}
|
||||
|
||||
const ecma_number_t *
|
||||
lexer_get_nums (void)
|
||||
const ecma_char_t *
|
||||
lexer_get_strings_cache (void)
|
||||
{
|
||||
ecma_number_t *data = NULL;
|
||||
STACK_CONVERT_TO_RAW_DATA (numbers, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
lexer_get_nums_count (void)
|
||||
{
|
||||
return STACK_SIZE (numbers);
|
||||
return strings_cache;
|
||||
}
|
||||
|
||||
void
|
||||
lexer_adjust_num_ids (void)
|
||||
lexer_add_literal_if_not_present (literal lit)
|
||||
{
|
||||
JERRY_ASSERT (STACK_SIZE (numbers) == STACK_SIZE (num_ids));
|
||||
for (uint8_t i = 0; i < STACK_SIZE (numbers); i++)
|
||||
for (uint8_t i = 0; i < STACK_SIZE (literals); i++)
|
||||
{
|
||||
STACK_SET_ELEMENT (num_ids, i, (uint8_t) (STACK_ELEMENT (num_ids, i) + STACK_SIZE (strings)));
|
||||
if (literal_equal_type (STACK_ELEMENT (literals, i), lit))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ecma_number_t
|
||||
lexer_get_num_by_id (uint8_t id)
|
||||
{
|
||||
JERRY_ASSERT (id >= lexer_get_strings_count () && id < lexer_get_reserved_ids_count ());
|
||||
JERRY_ASSERT (STACK_ELEMENT (num_ids, id - lexer_get_strings_count ()) == id);
|
||||
return STACK_ELEMENT (numbers, id - lexer_get_strings_count ());
|
||||
STACK_PUSH (literals, lit);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -989,14 +1003,6 @@ lexer_set_source (const char * source)
|
||||
buffer = buffer_start;
|
||||
}
|
||||
|
||||
static void
|
||||
lexer_rewind (void)
|
||||
{
|
||||
JERRY_ASSERT (buffer_start != NULL);
|
||||
|
||||
buffer = buffer_start;
|
||||
}
|
||||
|
||||
static bool
|
||||
replace_comment_by_newline (void)
|
||||
{
|
||||
@@ -1229,18 +1235,6 @@ lexer_prev_token (void)
|
||||
return prev_token;
|
||||
}
|
||||
|
||||
void
|
||||
lexer_run_first_pass (void)
|
||||
{
|
||||
token tok = lexer_next_token ();
|
||||
while (tok.type != TOK_EOF)
|
||||
{
|
||||
tok = lexer_next_token ();
|
||||
}
|
||||
|
||||
lexer_rewind ();
|
||||
}
|
||||
|
||||
void
|
||||
lexer_seek (size_t locus)
|
||||
{
|
||||
@@ -1307,34 +1301,53 @@ lexer_keyword_to_string (keyword kw)
|
||||
case KW_BREAK: return "break";
|
||||
case KW_CASE: return "case";
|
||||
case KW_CATCH: return "catch";
|
||||
case KW_CLASS: return "class";
|
||||
|
||||
case KW_CONST: return "const";
|
||||
case KW_CONTINUE: return "continue";
|
||||
case KW_DEBUGGER: return "debugger";
|
||||
case KW_DEFAULT: return "default";
|
||||
case KW_DELETE: return "delete";
|
||||
case KW_DO: return "do";
|
||||
|
||||
case KW_DO: return "do";
|
||||
case KW_ELSE: return "else";
|
||||
case KW_ENUM: return "enum";
|
||||
case KW_EXPORT: return "export";
|
||||
case KW_EXTENDS: return "extends";
|
||||
|
||||
case KW_FINALLY: return "finally";
|
||||
case KW_FOR: return "for";
|
||||
case KW_FUNCTION: return "function";
|
||||
case KW_IF: return "if";
|
||||
|
||||
case KW_IN: return "in";
|
||||
case KW_INSTANCEOF: return "instanceof";
|
||||
case KW_NEW: return "new";
|
||||
case KW_RETURN: return "return";
|
||||
case KW_SWITCH: return "switch";
|
||||
|
||||
case KW_INSTANCEOF: return "instanceof";
|
||||
case KW_INTERFACE: return "interface";
|
||||
case KW_IMPORT: return "import";
|
||||
case KW_IMPLEMENTS: return "implements";
|
||||
case KW_LET: return "let";
|
||||
|
||||
case KW_NEW: return "new";
|
||||
case KW_PACKAGE: return "package";
|
||||
case KW_PRIVATE: return "private";
|
||||
case KW_PROTECTED: return "protected";
|
||||
case KW_PUBLIC: return "public";
|
||||
|
||||
case KW_RETURN: return "return";
|
||||
case KW_STATIC: return "static";
|
||||
case KW_SUPER: return "super";
|
||||
case KW_SWITCH: return "switch";
|
||||
case KW_THIS: return "this";
|
||||
|
||||
case KW_THROW: return "throw";
|
||||
case KW_TRY: return "try";
|
||||
case KW_TYPEOF: return "typeof";
|
||||
case KW_VAR: return "var";
|
||||
|
||||
case KW_VOID: return "void";
|
||||
|
||||
case KW_WHILE: return "while";
|
||||
case KW_WITH: return "with";
|
||||
case KW_YIELD: return "yield";
|
||||
default: JERRY_UNREACHABLE ();
|
||||
}
|
||||
}
|
||||
@@ -1423,23 +1436,14 @@ lexer_init (const char *source, size_t source_size, bool show_opcodes)
|
||||
allow_dump_lines = show_opcodes;
|
||||
buffer_size = source_size;
|
||||
lexer_set_source (source);
|
||||
strings_cache_size = mem_heap_recommend_allocation_size (sizeof (ecma_char_t));
|
||||
strings_cache = (ecma_char_t *) mem_heap_alloc_block (strings_cache_size, MEM_HEAP_ALLOC_SHORT_TERM);
|
||||
strings_cache_used_size = 0;
|
||||
strings_cache = NULL;
|
||||
strings_cache_used_size = strings_cache_size = 0;
|
||||
|
||||
STACK_INIT (strings);
|
||||
STACK_INIT (numbers);
|
||||
STACK_INIT (num_ids);
|
||||
STACK_INIT (literals);
|
||||
}
|
||||
|
||||
void
|
||||
lexer_free (void)
|
||||
{
|
||||
if (STACK_SIZE (strings) == 0)
|
||||
{
|
||||
mem_heap_free_block (strings_cache);
|
||||
}
|
||||
STACK_FREE (strings);
|
||||
STACK_FREE (numbers);
|
||||
STACK_FREE (num_ids);
|
||||
STACK_FREE (literals);
|
||||
}
|
||||
|
||||
+30
-16
@@ -18,8 +18,10 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "lp-string.h"
|
||||
#include "literal.h"
|
||||
#include "opcodes.h"
|
||||
|
||||
#define INVALID_VALUE 255
|
||||
/* Keywords. */
|
||||
typedef enum
|
||||
{
|
||||
@@ -28,13 +30,19 @@ typedef enum
|
||||
KW_BREAK,
|
||||
KW_CASE,
|
||||
KW_CATCH,
|
||||
KW_CONTINUE,
|
||||
KW_CLASS,
|
||||
|
||||
KW_CONST,
|
||||
KW_CONTINUE,
|
||||
KW_DEBUGGER,
|
||||
KW_DEFAULT,
|
||||
KW_DELETE,
|
||||
|
||||
KW_DO,
|
||||
KW_ELSE,
|
||||
KW_ENUM,
|
||||
KW_EXPORT,
|
||||
KW_EXTENDS,
|
||||
|
||||
KW_FINALLY,
|
||||
KW_FOR,
|
||||
@@ -43,8 +51,20 @@ typedef enum
|
||||
KW_IN,
|
||||
|
||||
KW_INSTANCEOF,
|
||||
KW_INTERFACE,
|
||||
KW_IMPORT,
|
||||
KW_IMPLEMENTS,
|
||||
KW_LET,
|
||||
|
||||
KW_NEW,
|
||||
KW_PACKAGE,
|
||||
KW_PRIVATE,
|
||||
KW_PROTECTED,
|
||||
KW_PUBLIC,
|
||||
|
||||
KW_RETURN,
|
||||
KW_STATIC,
|
||||
KW_SUPER,
|
||||
KW_SWITCH,
|
||||
KW_THIS,
|
||||
|
||||
@@ -56,6 +76,7 @@ typedef enum
|
||||
|
||||
KW_WHILE,
|
||||
KW_WITH,
|
||||
KW_YIELD
|
||||
}
|
||||
keyword;
|
||||
|
||||
@@ -142,30 +163,23 @@ typedef struct
|
||||
{
|
||||
locus loc;
|
||||
token_type type;
|
||||
uint8_t uid;
|
||||
idx_t uid;
|
||||
}
|
||||
token;
|
||||
|
||||
void lexer_init (const char *, size_t, bool);
|
||||
void lexer_free (void);
|
||||
|
||||
void lexer_run_first_pass (void);
|
||||
|
||||
token lexer_next_token (void);
|
||||
void lexer_save_token (token);
|
||||
token lexer_prev_token (void);
|
||||
|
||||
uint8_t lexer_get_reserved_ids_count (void);
|
||||
|
||||
const lp_string *lexer_get_strings (void);
|
||||
uint8_t lexer_get_strings_count (void);
|
||||
lp_string lexer_get_string_by_id (uint8_t);
|
||||
|
||||
const ecma_number_t *lexer_get_nums (void);
|
||||
ecma_number_t lexer_get_num_by_id (uint8_t);
|
||||
uint8_t lexer_get_nums_count (void);
|
||||
|
||||
void lexer_adjust_num_ids (void);
|
||||
const literal *lexer_get_literals (void);
|
||||
const ecma_char_t *lexer_get_strings_cache (void);
|
||||
void lexer_add_literal_if_not_present (literal);
|
||||
uint8_t lexer_get_literals_count (void);
|
||||
literal lexer_get_literal_by_id (uint8_t);
|
||||
idx_t lexer_lookup_literal_uid (literal lit);
|
||||
|
||||
void lexer_seek (locus);
|
||||
void lexer_locus_to_line_and_column (locus, size_t *, size_t *);
|
||||
|
||||
+202
-268
@@ -28,7 +28,6 @@
|
||||
#include "scopes-tree.h"
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
#define INVALID_VALUE 255
|
||||
#define INTRINSICS_COUNT 1
|
||||
|
||||
typedef enum
|
||||
@@ -39,17 +38,6 @@ typedef enum
|
||||
}
|
||||
rewritable_opcode_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
void (*fun1) (idx_t);
|
||||
}
|
||||
funs;
|
||||
uint8_t args_count;
|
||||
}
|
||||
intrinsic_dumper;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PROP_DATA,
|
||||
@@ -59,19 +47,12 @@ typedef enum
|
||||
}
|
||||
prop_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
lp_string str;
|
||||
bool was_num;
|
||||
}
|
||||
allocatable_string;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
prop_type type;
|
||||
allocatable_string str;
|
||||
literal lit;
|
||||
}
|
||||
prop_as_str_or_varg;
|
||||
prop_literal;
|
||||
|
||||
#define NESTING_ITERATIONAL 1
|
||||
#define NESTING_SWITCH 2
|
||||
@@ -88,7 +69,6 @@ STATIC_STACK (U8, uint8_t, uint8_t)
|
||||
|
||||
enum
|
||||
{
|
||||
native_calls = OPCODE_NATIVE_CALL__COUNT,
|
||||
this_arg,
|
||||
prop,
|
||||
IDX_global_size
|
||||
@@ -199,15 +179,15 @@ STATIC_STACK (rewritable_break, uint8_t, uint16_t)
|
||||
|
||||
enum
|
||||
{
|
||||
strings_global_size
|
||||
literals_global_size
|
||||
};
|
||||
STATIC_STACK (strings, uint8_t, allocatable_string)
|
||||
STATIC_STACK (literals, uint8_t, literal)
|
||||
|
||||
enum
|
||||
{
|
||||
props_global_size
|
||||
};
|
||||
STATIC_STACK (props, uint8_t, prop_as_str_or_varg)
|
||||
STATIC_STACK (props, uint8_t, prop_literal)
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
#define STACK_CHECK_USAGE_LHS() \
|
||||
@@ -216,9 +196,6 @@ JERRY_ASSERT (IDX.current == IDX_current + 1);
|
||||
#define STACK_CHECK_USAGE_LHS() ;
|
||||
#endif
|
||||
|
||||
static uint8_t lp_string_hash (lp_string);
|
||||
STATIC_HASH_TABLE (intrinsics, lp_string, intrinsic_dumper)
|
||||
|
||||
#define LAST_OPCODE_IS(OP) (deserialize_opcode((opcode_counter_t)(OPCODE_COUNTER()-1)).op_idx == __op__idx_##OP)
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (idx_t) == sizeof (uint8_t));
|
||||
@@ -356,12 +333,6 @@ static uint8_t parse_argument_list (argument_list_type, idx_t);
|
||||
static void skip_braces (void);
|
||||
static void parse_logical_expression (bool);
|
||||
|
||||
static uint8_t
|
||||
lp_string_hash (lp_string str)
|
||||
{
|
||||
return str.length % INTRINSICS_COUNT;
|
||||
}
|
||||
|
||||
static idx_t
|
||||
next_temp_name (void)
|
||||
{
|
||||
@@ -622,22 +593,6 @@ dump_assert (idx_t arg)
|
||||
DUMP_OPCODE_1 (exitval, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_intrinsics (void)
|
||||
{
|
||||
lp_string str = (lp_string)
|
||||
{
|
||||
.length = 6,
|
||||
.str = (ecma_char_t *) "assert"
|
||||
};
|
||||
intrinsic_dumper dumper = (intrinsic_dumper)
|
||||
{
|
||||
.args_count = 1,
|
||||
.funs.fun1 = dump_assert
|
||||
};
|
||||
HASH_INSERT (intrinsics, str, dumper);
|
||||
}
|
||||
|
||||
static bool
|
||||
is_intrinsic (idx_t obj)
|
||||
{
|
||||
@@ -649,10 +604,10 @@ is_intrinsic (idx_t obj)
|
||||
|
||||
STACK_DECLARE_USAGE (U8)
|
||||
|
||||
STACK_PUSH (U8, lexer_get_strings_count ());
|
||||
STACK_PUSH (U8, lexer_get_literals_count ());
|
||||
if (obj < STACK_TOP (U8))
|
||||
{
|
||||
if (HASH_LOOKUP (intrinsics, lexer_get_string_by_id (obj)) != NULL)
|
||||
if (literal_equal_type_s (lexer_get_literal_by_id (obj), "assert"))
|
||||
{
|
||||
result = true;
|
||||
goto cleanup;
|
||||
@@ -669,131 +624,65 @@ cleanup:
|
||||
static void
|
||||
dump_intrinsic (idx_t obj, idx_t arg)
|
||||
{
|
||||
if (obj < lexer_get_strings_count ())
|
||||
if (obj < lexer_get_literals_count ())
|
||||
{
|
||||
intrinsic_dumper *dumper = HASH_LOOKUP (intrinsics, lexer_get_string_by_id (obj));
|
||||
|
||||
JERRY_ASSERT (dumper);
|
||||
|
||||
switch (dumper->args_count)
|
||||
if (literal_equal_type_s (lexer_get_literal_by_id (obj), "assert"))
|
||||
{
|
||||
case 1: dumper->funs.fun1 (arg); return;
|
||||
default: JERRY_UNREACHABLE ();
|
||||
dump_assert (arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
|
||||
static bool
|
||||
is_native_call (idx_t obj)
|
||||
{
|
||||
if (obj >= lexer_get_strings_count ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < OPCODE_NATIVE_CALL__COUNT; i++)
|
||||
{
|
||||
if (STACK_ELEMENT (IDX, i) == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static idx_t
|
||||
name_to_native_call_id (idx_t obj)
|
||||
{
|
||||
JERRY_ASSERT (obj < lexer_get_strings_count ());
|
||||
|
||||
for (uint8_t i = 0; i < OPCODE_NATIVE_CALL__COUNT; i++)
|
||||
if (obj >= lexer_get_literals_count ())
|
||||
{
|
||||
if (STACK_ELEMENT (IDX, i) == obj)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
return OPCODE_NATIVE_CALL__COUNT;
|
||||
}
|
||||
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
|
||||
static void
|
||||
free_allocatable_string (prop_as_str_or_varg p)
|
||||
{
|
||||
if (p.str.was_num)
|
||||
if (literal_equal_type_s (lexer_get_literal_by_id (obj), "LEDToggle"))
|
||||
{
|
||||
mem_heap_free_block ((uint8_t *) p.str.str.str);
|
||||
return OPCODE_NATIVE_CALL_LED_TOGGLE;
|
||||
}
|
||||
}
|
||||
|
||||
static allocatable_string
|
||||
create_allocatable_string_from_num_uid (idx_t uid)
|
||||
{
|
||||
ecma_char_t *str = mem_heap_alloc_block (ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER * sizeof (ecma_char_t),
|
||||
MEM_HEAP_ALLOC_SHORT_TERM);
|
||||
ecma_number_to_zt_string (lexer_get_num_by_id (uid), str,
|
||||
ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER * sizeof (ecma_char_t));
|
||||
|
||||
return (allocatable_string)
|
||||
else if (literal_equal_type_s (lexer_get_literal_by_id (obj), "LEDOn"))
|
||||
{
|
||||
.was_num = true,
|
||||
.str = (lp_string)
|
||||
{
|
||||
.length = ecma_zt_string_length (str),
|
||||
.str = str
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static allocatable_string
|
||||
create_allocatable_string_from_literal (idx_t uid)
|
||||
{
|
||||
return (allocatable_string)
|
||||
{
|
||||
.was_num = false,
|
||||
.str = lexer_get_string_by_id (uid)
|
||||
};
|
||||
}
|
||||
|
||||
static allocatable_string
|
||||
create_allocatable_string_from_small_int (idx_t uid)
|
||||
{
|
||||
const uint8_t chars_need = 4; /* Max is 255. */
|
||||
uint8_t index = 0;
|
||||
ecma_char_t *str = mem_heap_alloc_block (chars_need * sizeof (ecma_char_t),
|
||||
MEM_HEAP_ALLOC_SHORT_TERM);
|
||||
if (uid >= 100)
|
||||
{
|
||||
str[index++] = (ecma_char_t) (uid/100 + '0');
|
||||
uid %= 100;
|
||||
return OPCODE_NATIVE_CALL_LED_ON;
|
||||
}
|
||||
if (uid >= 10)
|
||||
else if (literal_equal_type_s (lexer_get_literal_by_id (obj), "LEDOff"))
|
||||
{
|
||||
str[index++] = (ecma_char_t) (uid/10 + '0');
|
||||
return OPCODE_NATIVE_CALL_LED_OFF;
|
||||
}
|
||||
str[index++] = (ecma_char_t) (uid%10 + '0');
|
||||
str[index] = ECMA_CHAR_NULL;
|
||||
|
||||
return (allocatable_string)
|
||||
else if (literal_equal_type_s (lexer_get_literal_by_id (obj), "LEDOnce"))
|
||||
{
|
||||
.was_num = true,
|
||||
.str = (lp_string)
|
||||
{
|
||||
.length = index,
|
||||
.str = str
|
||||
}
|
||||
};
|
||||
return OPCODE_NATIVE_CALL_LED_ONCE;
|
||||
}
|
||||
else if (literal_equal_type_s (lexer_get_literal_by_id (obj), "wait"))
|
||||
{
|
||||
return OPCODE_NATIVE_CALL_WAIT;
|
||||
}
|
||||
else if (literal_equal_type_s (lexer_get_literal_by_id (obj), "print"))
|
||||
{
|
||||
return OPCODE_NATIVE_CALL_PRINT;
|
||||
}
|
||||
return OPCODE_NATIVE_CALL__COUNT;
|
||||
}
|
||||
|
||||
static prop_as_str_or_varg
|
||||
create_prop_as_str_or_varg (allocatable_string str, prop_type type)
|
||||
static bool
|
||||
is_native_call (idx_t obj)
|
||||
{
|
||||
return (prop_as_str_or_varg)
|
||||
return name_to_native_call_id (obj) < OPCODE_NATIVE_CALL__COUNT;
|
||||
}
|
||||
|
||||
static prop_literal
|
||||
create_prop_literal (literal lit, prop_type type)
|
||||
{
|
||||
return (prop_literal)
|
||||
{
|
||||
.type = type,
|
||||
.str = str
|
||||
.lit = lit
|
||||
};
|
||||
}
|
||||
|
||||
@@ -814,21 +703,30 @@ parse_property_name (void)
|
||||
{
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_STRING, token_data ());
|
||||
STACK_PUSH (strings, create_allocatable_string_from_literal (token_data ()));
|
||||
STACK_PUSH (literals, lexer_get_literal_by_id (token_data ()));
|
||||
break;
|
||||
}
|
||||
case TOK_NUMBER:
|
||||
{
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_NUMBER, token_data ());
|
||||
STACK_PUSH (strings, create_allocatable_string_from_num_uid (token_data ()));
|
||||
STACK_PUSH (literals, lexer_get_literal_by_id (token_data ()));
|
||||
break;
|
||||
}
|
||||
case TOK_SMALL_INT:
|
||||
{
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_SMALLINT, token_data ());
|
||||
STACK_PUSH (strings, create_allocatable_string_from_small_int (token_data ()));
|
||||
STACK_PUSH (literals, create_literal_from_num ((ecma_number_t) token_data ()));
|
||||
break;
|
||||
}
|
||||
case TOK_KEYWORD:
|
||||
{
|
||||
literal lit = create_literal_from_str_compute_len (lexer_keyword_to_string (token_data ()));
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_STRING,
|
||||
lexer_lookup_literal_uid (lit));
|
||||
STACK_PUSH (literals, lit);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -856,8 +754,8 @@ parse_property_name_and_value (void)
|
||||
|
||||
DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_VARG_PROP_DATA, STACK_HEAD(IDX, 2), STACK_HEAD(IDX, 1));
|
||||
|
||||
STACK_PUSH (props, create_prop_as_str_or_varg (STACK_TOP (strings), PROP_DATA));
|
||||
STACK_DROP (strings, 1);
|
||||
STACK_PUSH (props, create_prop_literal (STACK_TOP (literals), PROP_DATA));
|
||||
STACK_DROP (literals, 1);
|
||||
|
||||
STACK_DROP (IDX, 2);
|
||||
STACK_CHECK_USAGE (IDX);
|
||||
@@ -912,7 +810,7 @@ parse_property_assignment (void)
|
||||
STACK_DECLARE_USAGE (U16)
|
||||
STACK_DECLARE_USAGE (toks)
|
||||
STACK_DECLARE_USAGE (U8)
|
||||
STACK_DECLARE_USAGE (strings)
|
||||
STACK_DECLARE_USAGE (literals)
|
||||
|
||||
if (!token_is (TOK_NAME))
|
||||
{
|
||||
@@ -920,7 +818,7 @@ parse_property_assignment (void)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (lp_string_equal_s (lexer_get_string_by_id (token_data ()), "get"))
|
||||
if (literal_equal_type_s (lexer_get_literal_by_id (token_data ()), "get"))
|
||||
{
|
||||
STACK_PUSH (toks, TOK ());
|
||||
skip_newlines ();
|
||||
@@ -934,8 +832,8 @@ parse_property_assignment (void)
|
||||
STACK_DROP (toks, 1);
|
||||
// name, lhs
|
||||
parse_property_name (); // push name
|
||||
STACK_PUSH (props, create_prop_as_str_or_varg (STACK_TOP (strings), PROP_GET));
|
||||
STACK_DROP (strings, 1);
|
||||
STACK_PUSH (props, create_prop_literal (STACK_TOP (literals), PROP_GET));
|
||||
STACK_DROP (literals, 1);
|
||||
|
||||
skip_newlines ();
|
||||
parse_argument_list (AL_FUNC_EXPR, next_temp_name ()); // push lhs
|
||||
@@ -967,7 +865,7 @@ parse_property_assignment (void)
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
else if (lp_string_equal_s (lexer_get_string_by_id (token_data ()), "set"))
|
||||
else if (literal_equal_type_s (lexer_get_literal_by_id (token_data ()), "set"))
|
||||
{
|
||||
STACK_PUSH (toks, TOK ());
|
||||
skip_newlines ();
|
||||
@@ -981,8 +879,8 @@ parse_property_assignment (void)
|
||||
STACK_DROP (toks, 1);
|
||||
// name, lhs
|
||||
parse_property_name (); // push name
|
||||
STACK_PUSH (props, create_prop_as_str_or_varg (STACK_TOP (strings), PROP_SET));
|
||||
STACK_DROP (strings, 1);
|
||||
STACK_PUSH (props, create_prop_literal (STACK_TOP (literals), PROP_SET));
|
||||
STACK_DROP (literals, 1);
|
||||
|
||||
skip_newlines ();
|
||||
parse_argument_list (AL_FUNC_EXPR, next_temp_name ()); // push lhs
|
||||
@@ -1019,7 +917,7 @@ simple_prop:
|
||||
parse_property_name_and_value ();
|
||||
|
||||
cleanup:
|
||||
STACK_CHECK_USAGE (strings);
|
||||
STACK_CHECK_USAGE (literals);
|
||||
STACK_CHECK_USAGE (U8);
|
||||
STACK_CHECK_USAGE (toks);
|
||||
STACK_CHECK_USAGE (U16);
|
||||
@@ -1029,12 +927,12 @@ cleanup:
|
||||
static void
|
||||
emit_error_on_eval_and_arguments (idx_t id)
|
||||
{
|
||||
if (id < lexer_get_strings_count ())
|
||||
if (id < lexer_get_literals_count ())
|
||||
{
|
||||
if (lp_string_equal_zt (lexer_get_string_by_id (id),
|
||||
ecma_get_magic_string_zt (ECMA_MAGIC_STRING_ARGUMENTS))
|
||||
|| lp_string_equal_zt (lexer_get_string_by_id (id),
|
||||
ecma_get_magic_string_zt (ECMA_MAGIC_STRING_EVAL)))
|
||||
if (literal_equal_type_zt (lexer_get_literal_by_id (id),
|
||||
ecma_get_magic_string_zt (ECMA_MAGIC_STRING_ARGUMENTS))
|
||||
|| literal_equal_type_zt (lexer_get_literal_by_id (id),
|
||||
ecma_get_magic_string_zt (ECMA_MAGIC_STRING_EVAL)))
|
||||
{
|
||||
EMIT_ERROR ("'eval' and 'arguments' are not allowed here in strict mode");
|
||||
}
|
||||
@@ -1061,12 +959,17 @@ check_for_syntax_errors_in_formal_param_list (uint8_t from)
|
||||
for (uint8_t i = (uint8_t) (from + 1); i < STACK_SIZE (props); i = (uint8_t) (i + 1))
|
||||
{
|
||||
JERRY_ASSERT (STACK_ELEMENT (props, i).type == VARG);
|
||||
const literal previous = STACK_ELEMENT (props, i).lit;
|
||||
JERRY_ASSERT (previous.type == LIT_STR || previous.type == LIT_MAGIC_STR);
|
||||
for (uint8_t j = from; j < i; j = (uint8_t) (j + 1))
|
||||
{
|
||||
if (lp_string_equal (STACK_ELEMENT (props, i).str.str, STACK_ELEMENT (props, j).str.str))
|
||||
JERRY_ASSERT (STACK_ELEMENT (props, j).type == VARG);
|
||||
const literal current = STACK_ELEMENT (props, j).lit;
|
||||
JERRY_ASSERT (current.type == LIT_STR || current.type == LIT_MAGIC_STR);
|
||||
if (literal_equal_type (previous, current))
|
||||
{
|
||||
EMIT_ERROR_VARG ("Duplication of literal '%s' in FormalParameterList is not allowed in strict mode",
|
||||
STACK_ELEMENT (props, j).str.str.str);
|
||||
(const char *) literal_to_zt (previous));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1083,44 +986,45 @@ check_for_syntax_errors_in_obj_decl (uint8_t from)
|
||||
|
||||
for (uint8_t i = (uint8_t) (from + 1); i < STACK_SIZE (props); i = (uint8_t) (i + 1))
|
||||
{
|
||||
JERRY_ASSERT (STACK_ELEMENT (props, i).type == PROP_DATA
|
||||
|| STACK_ELEMENT (props, i).type == PROP_GET
|
||||
|| STACK_ELEMENT (props, i).type == PROP_SET);
|
||||
const prop_literal previous = STACK_ELEMENT (props, i);
|
||||
JERRY_ASSERT (previous.type == PROP_DATA
|
||||
|| previous.type == PROP_GET
|
||||
|| previous.type == PROP_SET);
|
||||
for (uint8_t j = from; j < i; j = (uint8_t) (j + 1))
|
||||
{
|
||||
/*4*/
|
||||
const lp_string previous = STACK_ELEMENT (props, j).str.str;
|
||||
const prop_type prop_type_previous = STACK_ELEMENT (props, j).type;
|
||||
const lp_string prop_id_desc = STACK_ELEMENT (props, i).str.str;
|
||||
const prop_type prop_type_prop_id_desc = STACK_ELEMENT (props, i).type;
|
||||
if (lp_string_equal (previous, prop_id_desc))
|
||||
const prop_literal current = STACK_ELEMENT (props, j);
|
||||
JERRY_ASSERT (current.type == PROP_DATA
|
||||
|| current.type == PROP_GET
|
||||
|| current.type == PROP_SET);
|
||||
if (literal_equal (previous.lit, current.lit))
|
||||
{
|
||||
/*a*/
|
||||
if (parser_strict_mode () && prop_type_previous == PROP_DATA && prop_type_prop_id_desc == PROP_DATA)
|
||||
if (parser_strict_mode () && previous.type == PROP_DATA && current.type == PROP_DATA)
|
||||
{
|
||||
EMIT_ERROR_VARG ("Duplication of parameter name '%s' in ObjectDeclaration is not allowed in strict mode",
|
||||
previous.str);
|
||||
(const char *) literal_to_zt (current.lit));
|
||||
}
|
||||
/*b*/
|
||||
if (prop_type_previous == PROP_DATA
|
||||
&& (prop_type_prop_id_desc == PROP_SET || prop_type_prop_id_desc == PROP_GET))
|
||||
if (previous.type == PROP_DATA
|
||||
&& (current.type == PROP_SET || current.type == PROP_GET))
|
||||
{
|
||||
EMIT_ERROR_VARG ("Parameter name '%s' in ObjectDeclaration may not be both data and accessor",
|
||||
previous.str);
|
||||
(const char *) literal_to_zt (current.lit));
|
||||
}
|
||||
/*c*/
|
||||
if (prop_type_prop_id_desc == PROP_DATA
|
||||
&& (prop_type_previous == PROP_SET || prop_type_previous == PROP_GET))
|
||||
if (current.type == PROP_DATA
|
||||
&& (previous.type == PROP_SET || previous.type == PROP_GET))
|
||||
{
|
||||
EMIT_ERROR_VARG ("Parameter name '%s' in ObjectDeclaration may not be both data and accessor",
|
||||
previous.str);
|
||||
(const char *) literal_to_zt (current.lit));
|
||||
}
|
||||
/*d*/
|
||||
if ((prop_type_previous == PROP_SET && prop_type_prop_id_desc == PROP_SET)
|
||||
|| (prop_type_previous == PROP_GET && prop_type_prop_id_desc == PROP_GET))
|
||||
if ((previous.type == PROP_SET && current.type == PROP_SET)
|
||||
|| (previous.type == PROP_GET && current.type == PROP_GET))
|
||||
{
|
||||
EMIT_ERROR_VARG ("Parameter name '%s' in ObjectDeclaration may not be accessor of same type",
|
||||
previous.str);
|
||||
(const char *) literal_to_zt (current.lit));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,8 +1142,8 @@ parse_argument_list (argument_list_type alt, idx_t obj)
|
||||
current_token_must_be (TOK_NAME);
|
||||
STACK_PUSH (IDX, token_data ());
|
||||
STACK_PUSH (props,
|
||||
create_prop_as_str_or_varg (create_allocatable_string_from_literal (token_data ()),
|
||||
VARG));
|
||||
create_prop_literal (lexer_get_literal_by_id (token_data ()),
|
||||
VARG));
|
||||
check_for_eval_and_arguments_in_strict_mode (STACK_TOP (IDX));
|
||||
break;
|
||||
}
|
||||
@@ -1358,8 +1262,6 @@ next:
|
||||
|
||||
const uint8_t args_num = STACK_TOP (U8);
|
||||
|
||||
STACK_ITERATE (props, free_allocatable_string, STACK_HEAD (U8, 4));
|
||||
|
||||
STACK_DROP (props, (uint8_t) (STACK_SIZE (props) - STACK_HEAD (U8, 4)));
|
||||
STACK_DROP (U8, 4);
|
||||
STACK_DROP (U16, 1);
|
||||
@@ -1722,13 +1624,28 @@ parse_member_expression (void)
|
||||
else if (token_is (TOK_DOT))
|
||||
{
|
||||
skip_newlines ();
|
||||
if (!token_is (TOK_NAME))
|
||||
if (token_is (TOK_NAME))
|
||||
{
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
SET_PROP (ID (1));
|
||||
DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_STRING, token_data ());
|
||||
}
|
||||
else if (token_is (TOK_KEYWORD))
|
||||
{
|
||||
const literal lit = create_literal_from_str_compute_len (lexer_keyword_to_string (token_data ()));
|
||||
const idx_t uid = lexer_lookup_literal_uid (lit);
|
||||
if (uid == INVALID_VALUE)
|
||||
{
|
||||
EMIT_ERROR ("Expected identifier");
|
||||
}
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
SET_PROP (ID (1));
|
||||
DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_STRING, uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
EMIT_ERROR ("Expected identifier");
|
||||
}
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
SET_PROP (ID (1));
|
||||
DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_STRING, token_data ());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1778,7 +1695,7 @@ parse_call_expression (void)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (THIS_ARG () < lexer_get_reserved_ids_count ())
|
||||
if (THIS_ARG () < lexer_get_literals_count ())
|
||||
{
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_VARIABLE, THIS_ARG ());
|
||||
@@ -1899,6 +1816,15 @@ cleanup:
|
||||
STACK_CHECK_USAGE_LHS ();
|
||||
}
|
||||
|
||||
static void
|
||||
dump_boolean_true (void)
|
||||
{
|
||||
STACK_DECLARE_USAGE (IDX);
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
DUMP_OPCODE_3 (assignment, ID (1), OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_TRUE);
|
||||
STACK_CHECK_USAGE_LHS ();
|
||||
}
|
||||
|
||||
/* unary_expression
|
||||
: postfix_expression
|
||||
| ('delete' | 'void' | 'typeof' | '++' | '--' | '+' | '-' | '~' | '!') unary_expression
|
||||
@@ -1971,17 +1897,31 @@ parse_unary_expression (void)
|
||||
if (is_keyword (KW_DELETE))
|
||||
{
|
||||
NEXT (unary_expression);
|
||||
if (ID (1) < lexer_get_strings_count ())
|
||||
if (ID (1) < lexer_get_literals_count ())
|
||||
{
|
||||
if (parser_strict_mode ())
|
||||
literal lit = lexer_get_literal_by_id (ID (1));
|
||||
if (lit.type == LIT_MAGIC_STR || lit.type == LIT_STR)
|
||||
{
|
||||
EMIT_ERROR ("'delete' operator shall not apply on identifier in strict mode.");
|
||||
if (parser_strict_mode ())
|
||||
{
|
||||
EMIT_ERROR ("'delete' operator shall not apply on identifier in strict mode.");
|
||||
}
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
DUMP_OPCODE_2 (delete_var, ID (1), ID (2));
|
||||
STACK_SWAP (IDX);
|
||||
STACK_DROP (IDX, 1);
|
||||
break;
|
||||
}
|
||||
else if (lit.type == LIT_NUMBER)
|
||||
{
|
||||
dump_boolean_true ();
|
||||
STACK_SWAP (IDX);
|
||||
STACK_DROP (IDX, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
DUMP_OPCODE_2 (delete_var, ID (1), ID (2));
|
||||
STACK_SWAP (IDX);
|
||||
STACK_DROP (IDX, 1);
|
||||
break;
|
||||
}
|
||||
STACK_PUSH (ops, deserialize_opcode ((opcode_counter_t) (OPCODE_COUNTER () - 1)));
|
||||
if (LAST_OPCODE_IS (assignment)
|
||||
@@ -2002,8 +1942,7 @@ parse_unary_expression (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
STACK_PUSH (IDX, next_temp_name ());
|
||||
DUMP_OPCODE_3 (assignment, ID (1), OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_TRUE);
|
||||
dump_boolean_true ();
|
||||
STACK_SWAP (IDX);
|
||||
STACK_DROP (IDX, 1);
|
||||
}
|
||||
@@ -3769,6 +3708,44 @@ skip_braces (void)
|
||||
{
|
||||
STACK_DECR_HEAD (U8, 1);
|
||||
}
|
||||
else if (token_is (TOK_KEYWORD))
|
||||
{
|
||||
keyword kw = (keyword) token_data ();
|
||||
skip_newlines ();
|
||||
if (token_is (TOK_COLON))
|
||||
{
|
||||
lexer_add_literal_if_not_present (create_literal_from_str_compute_len (lexer_keyword_to_string (kw)));
|
||||
}
|
||||
else
|
||||
{
|
||||
lexer_save_token (TOK ());
|
||||
}
|
||||
}
|
||||
else if (token_is (TOK_NAME))
|
||||
{
|
||||
if (literal_equal_type_s (lexer_get_literal_by_id (token_data ()), "get")
|
||||
|| literal_equal_type_s (lexer_get_literal_by_id (token_data ()), "set"))
|
||||
{
|
||||
skip_newlines ();
|
||||
if (token_is (TOK_KEYWORD))
|
||||
{
|
||||
keyword kw = (keyword) token_data ();
|
||||
skip_newlines ();
|
||||
if (token_is (TOK_OPEN_PAREN))
|
||||
{
|
||||
lexer_add_literal_if_not_present (create_literal_from_str_compute_len (lexer_keyword_to_string (kw)));
|
||||
}
|
||||
else
|
||||
{
|
||||
lexer_save_token (TOK ());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lexer_save_token (TOK ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STACK_DROP (U8,1);
|
||||
@@ -3953,7 +3930,7 @@ preparse_scope (bool is_global)
|
||||
STACK_PUSH (locs, TOK ().loc);
|
||||
STACK_PUSH (U8, is_global ? TOK_EOF : TOK_CLOSE_BRACE);
|
||||
|
||||
if (token_is (TOK_STRING) && lp_string_equal_s (lexer_get_string_by_id (token_data ()), "use strict"))
|
||||
if (token_is (TOK_STRING) && literal_equal_s (lexer_get_literal_by_id (token_data ()), "use strict"))
|
||||
{
|
||||
scopes_tree_set_strict_mode (STACK_TOP (scopes), true);
|
||||
DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_STRICT_CODE, INVALID_VALUE, INVALID_VALUE);
|
||||
@@ -4011,9 +3988,16 @@ parse_source_element_list (bool is_global)
|
||||
STACK_DECLARE_USAGE (IDX)
|
||||
STACK_DECLARE_USAGE (temp_names)
|
||||
|
||||
start_new_scope ();
|
||||
preparse_scope (is_global);
|
||||
|
||||
preparse_scope (is_global);
|
||||
if (is_global)
|
||||
{
|
||||
SET_MAX_TEMP_NAME (lexer_get_literals_count ());
|
||||
SET_TEMP_NAME (lexer_get_literals_count ());
|
||||
SET_MIN_TEMP_NAME (lexer_get_literals_count ());
|
||||
}
|
||||
|
||||
start_new_scope ();
|
||||
skip_newlines ();
|
||||
while (!token_is (TOK_EOF) && !token_is (TOK_CLOSE_BRACE))
|
||||
{
|
||||
@@ -4050,10 +4034,12 @@ parser_parse_program (void)
|
||||
JERRY_ASSERT (token_is (TOK_EOF));
|
||||
DUMP_OPCODE_1 (exitval, 0);
|
||||
|
||||
serializer_dump_literals (lexer_get_literals (), lexer_get_literals_count ());
|
||||
serializer_merge_scopes_into_bytecode ();
|
||||
serializer_set_scope (NULL);
|
||||
deserializer_set_strings_buffer (lexer_get_strings_cache ());
|
||||
|
||||
scopes_tree_free (STACK_TOP (scopes));
|
||||
serializer_set_scope (NULL);
|
||||
STACK_DROP (scopes, 1);
|
||||
|
||||
STACK_CHECK_USAGE (IDX);
|
||||
@@ -4079,15 +4065,6 @@ parser_init (const char *source, size_t source_size, bool show_opcodes)
|
||||
lexer_init (source, source_size, show_opcodes);
|
||||
serializer_init (show_opcodes);
|
||||
|
||||
lexer_run_first_pass ();
|
||||
|
||||
lexer_adjust_num_ids ();
|
||||
|
||||
const lp_string *identifiers = lexer_get_strings ();
|
||||
|
||||
serializer_dump_strings_and_nums (identifiers, lexer_get_strings_count (),
|
||||
lexer_get_nums (), lexer_get_nums_count ());
|
||||
|
||||
STACK_INIT (U8);
|
||||
STACK_INIT (IDX);
|
||||
STACK_INIT (nestings);
|
||||
@@ -4100,51 +4077,10 @@ parser_init (const char *source, size_t source_size, bool show_opcodes)
|
||||
STACK_INIT (locs);
|
||||
STACK_INIT (scopes);
|
||||
STACK_INIT (props);
|
||||
STACK_INIT (strings);
|
||||
STACK_INIT (literals);
|
||||
|
||||
HASH_INIT (intrinsics, 1);
|
||||
|
||||
fill_intrinsics ();
|
||||
|
||||
SET_MAX_TEMP_NAME (lexer_get_reserved_ids_count ());
|
||||
SET_TEMP_NAME (lexer_get_reserved_ids_count ());
|
||||
SET_MIN_TEMP_NAME (lexer_get_reserved_ids_count ());
|
||||
SET_OPCODE_COUNTER (0);
|
||||
STACK_SET_ELEMENT (U8, no_in, 0);
|
||||
|
||||
TODO (/* Rewrite using hash when number of natives reaches 20 */)
|
||||
for (uint8_t i = 0; i < OPCODE_NATIVE_CALL__COUNT; i++)
|
||||
{
|
||||
STACK_SET_ELEMENT (IDX, i, INVALID_VALUE);
|
||||
}
|
||||
|
||||
for (uint8_t i = 0, strs_count = lexer_get_strings_count (); i < strs_count; i++)
|
||||
{
|
||||
if (lp_string_equal_s (identifiers[i], "LEDToggle"))
|
||||
{
|
||||
STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_TOGGLE, i);
|
||||
}
|
||||
else if (lp_string_equal_s (identifiers[i], "LEDOn"))
|
||||
{
|
||||
STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_ON, i);
|
||||
}
|
||||
else if (lp_string_equal_s (identifiers[i], "LEDOff"))
|
||||
{
|
||||
STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_OFF, i);
|
||||
}
|
||||
else if (lp_string_equal_s (identifiers[i], "LEDOnce"))
|
||||
{
|
||||
STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_ONCE, i);
|
||||
}
|
||||
else if (lp_string_equal_s (identifiers[i], "wait"))
|
||||
{
|
||||
STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_WAIT, i);
|
||||
}
|
||||
else if (lp_string_equal_s (identifiers[i], "print"))
|
||||
{
|
||||
STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_PRINT, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -4162,9 +4098,7 @@ parser_free (void)
|
||||
STACK_FREE (locs);
|
||||
STACK_FREE (scopes);
|
||||
STACK_FREE (props);
|
||||
STACK_FREE (strings);
|
||||
|
||||
HASH_FREE (intrinsics);
|
||||
STACK_FREE (literals);
|
||||
|
||||
serializer_free ();
|
||||
lexer_free ();
|
||||
|
||||
Reference in New Issue
Block a user