Add bytecode generator
This commit is contained in:
@@ -113,7 +113,7 @@ TARGET_MCU = -D__TARGET_MCU
|
|||||||
|
|
||||||
.PHONY: all debug debug.stdm32f4 release clean tests check install
|
.PHONY: all debug debug.stdm32f4 release clean tests check install
|
||||||
|
|
||||||
all: clean debug release check
|
all: debug release
|
||||||
|
|
||||||
debug.stdm32f4: clean debug.stdm32f4.bin
|
debug.stdm32f4: clean debug.stdm32f4.bin
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bytecode-generator.h"
|
||||||
|
#include "globals.h"
|
||||||
|
#include "libcoreint/opcodes.h"
|
||||||
|
#include "libruntime/serializer.h"
|
||||||
|
#include "libruntime/jerry-libc.h"
|
||||||
|
|
||||||
|
static uint8_t opcode_index;
|
||||||
|
|
||||||
|
#define MAX_STACK_SIZE 10
|
||||||
|
|
||||||
|
static uint8_t opcode_stack[10];
|
||||||
|
static uint8_t stack_head;
|
||||||
|
|
||||||
|
static void
|
||||||
|
push_opcode (uint8_t opcode)
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (stack_head < MAX_STACK_SIZE);
|
||||||
|
opcode_stack[stack_head++] = opcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t
|
||||||
|
pop_opcode (void)
|
||||||
|
{
|
||||||
|
return opcode_stack[--stack_head];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
generator_init (void)
|
||||||
|
{
|
||||||
|
opcode_index = 0;
|
||||||
|
stack_head = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
generator_dump_strings (const char **strings, uint8_t num)
|
||||||
|
{
|
||||||
|
uint8_t len = num, i;
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
serializer_dump_data (&len, 1);
|
||||||
|
len = (uint8_t) (len + __strlen (strings[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++)
|
||||||
|
serializer_dump_data (strings[i], __strlen (strings[i]) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
generator_dump_statement (statement stmt)
|
||||||
|
{
|
||||||
|
OPCODE opcode;
|
||||||
|
JERRY_STATIC_ASSERT (sizeof (OPCODE) <= sizeof (uint32_t));
|
||||||
|
|
||||||
|
switch (stmt.type)
|
||||||
|
{
|
||||||
|
case STMT_EMPTY:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STMT_WHILE:
|
||||||
|
TODO (Supports only infinite loops);
|
||||||
|
if (stmt.data.expr.oper == AO_NONE && stmt.data.expr.type == ET_NONE)
|
||||||
|
{
|
||||||
|
operand op = stmt.data.expr.data.ops.op1;
|
||||||
|
if (op.is_literal && op.data.lit.type == LIT_BOOL && op.data.lit.data.is_true)
|
||||||
|
{
|
||||||
|
opcode = getop_loop_inf ((uint8_t) (opcode_index + 1));
|
||||||
|
push_opcode ((uint8_t) (opcode_index + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STMT_EXPRESSION:
|
||||||
|
TODO (Supports only calls);
|
||||||
|
if (stmt.data.expr.oper == AO_NONE)
|
||||||
|
{
|
||||||
|
call_expression expr = stmt.data.expr.data.call_expr;
|
||||||
|
JERRY_ASSERT (!is_operand_list_empty (expr.args));
|
||||||
|
if (!is_operand_empty (expr.args.ops[1]))
|
||||||
|
JERRY_UNREACHABLE ();
|
||||||
|
if (expr.args.ops[0].is_literal)
|
||||||
|
JERRY_UNREACHABLE ();
|
||||||
|
opcode = getop_call_1 (expr.name, expr.args.ops[0].data.name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STMT_END_WHILE:
|
||||||
|
opcode = getop_jmp (pop_opcode ());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
__printf (" generator_dump_statement: %d ", stmt.type);
|
||||||
|
JERRY_UNREACHABLE ();
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer_dump_data (&opcode, sizeof (OPCODE));
|
||||||
|
opcode_index++;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BYTECODE_GENERATOR_H
|
||||||
|
#define BYTECODE_GENERATOR_H
|
||||||
|
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
void generator_init (void);
|
||||||
|
void generator_dump_strings (const char **, uint8_t);
|
||||||
|
void generator_dump_statement (statement);
|
||||||
|
|
||||||
|
#endif // BYTECODE_GENERATOR_H
|
||||||
+24
-3
@@ -81,7 +81,7 @@ static string_and_token keyword_tokens[] =
|
|||||||
#define MAX_NAMES 100
|
#define MAX_NAMES 100
|
||||||
|
|
||||||
static string_and_token seen_names[MAX_NAMES];
|
static string_and_token seen_names[MAX_NAMES];
|
||||||
static size_t seen_names_num;
|
static uint8_t seen_names_num;
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
is_empty (token tok)
|
is_empty (token tok)
|
||||||
@@ -210,9 +210,29 @@ add_to_seen_tokens (string_and_token snt)
|
|||||||
{
|
{
|
||||||
JERRY_ASSERT (seen_names_num < MAX_NAMES);
|
JERRY_ASSERT (seen_names_num < MAX_NAMES);
|
||||||
|
|
||||||
|
snt.tok.data.name = (string_id) seen_names_num;
|
||||||
seen_names[seen_names_num++] = snt;
|
seen_names[seen_names_num++] = snt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
lexer_get_strings (const char **strings)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < seen_names_num; i++)
|
||||||
|
strings[i] = seen_names[i].str;
|
||||||
|
|
||||||
|
return seen_names_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
lexer_get_string_by_id (string_id id)
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (id < seen_names_num);
|
||||||
|
|
||||||
|
return seen_names[id].str;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
new_token (void)
|
new_token (void)
|
||||||
{
|
{
|
||||||
@@ -318,7 +338,7 @@ parse_name (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
string = current_token ();
|
string = current_token ();
|
||||||
known_token = (token) { .type = TOK_NAME, .data.name = string };
|
known_token = (token) { .type = TOK_NAME, .data.name = seen_names_num };
|
||||||
|
|
||||||
add_to_seen_tokens ((string_and_token) { .str = string, .tok = known_token });
|
add_to_seen_tokens ((string_and_token) { .str = string, .tok = known_token });
|
||||||
|
|
||||||
@@ -561,7 +581,7 @@ parse_string (void)
|
|||||||
// Eat up '"'
|
// Eat up '"'
|
||||||
consume_char ();
|
consume_char ();
|
||||||
|
|
||||||
res = (token) { .type = TOK_STRING, .data.str = tok };
|
res = (token) { .type = TOK_STRING, .data.str = seen_names_num };
|
||||||
|
|
||||||
add_to_seen_tokens ((string_and_token) { .str = tok, .tok = res });
|
add_to_seen_tokens ((string_and_token) { .str = tok, .tok = res });
|
||||||
|
|
||||||
@@ -588,6 +608,7 @@ lexer_set_file (FILE *ex_file)
|
|||||||
file = ex_file;
|
file = ex_file;
|
||||||
lexer_debug_log = __fopen ("lexer.log", "w");
|
lexer_debug_log = __fopen ("lexer.log", "w");
|
||||||
saved_token = empty_token;
|
saved_token = empty_token;
|
||||||
|
buffer = buffer_start = token_start = NULL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
|
typedef uint8_t string_id;
|
||||||
|
|
||||||
/* Keywords. */
|
/* Keywords. */
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@@ -141,11 +143,11 @@ typedef struct
|
|||||||
{
|
{
|
||||||
void *none;
|
void *none;
|
||||||
keyword kw;
|
keyword kw;
|
||||||
const char *name;
|
string_id name;
|
||||||
bool is_true;
|
bool is_true;
|
||||||
int num;
|
int num;
|
||||||
float fp_num;
|
float fp_num;
|
||||||
const char *str;
|
string_id str;
|
||||||
}
|
}
|
||||||
data;
|
data;
|
||||||
}
|
}
|
||||||
@@ -161,4 +163,8 @@ void lexer_save_token (token);
|
|||||||
|
|
||||||
void lexer_dump_buffer_state (void);
|
void lexer_dump_buffer_state (void);
|
||||||
|
|
||||||
|
uint8_t lexer_get_strings (const char **);
|
||||||
|
|
||||||
|
const char *lexer_get_string_by_id (string_id id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+50
-27
@@ -20,7 +20,7 @@
|
|||||||
bool
|
bool
|
||||||
is_formal_parameter_list_empty (formal_parameter_list list)
|
is_formal_parameter_list_empty (formal_parameter_list list)
|
||||||
{
|
{
|
||||||
return list.names[0] == NULL;
|
return list.names[0] == null_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -56,7 +56,7 @@ is_expression_empty (assignment_expression expr)
|
|||||||
bool
|
bool
|
||||||
is_variable_declaration_empty (variable_declaration var_decl)
|
is_variable_declaration_empty (variable_declaration var_decl)
|
||||||
{
|
{
|
||||||
return var_decl.name == NULL && is_expression_empty (var_decl.assign_expr);
|
return var_decl.name == null_string && is_expression_empty (var_decl.assign_expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -65,7 +65,6 @@ is_statement_null (statement stmt)
|
|||||||
return stmt.type == STMT_NULL && stmt.data.none == NULL;
|
return stmt.type == STMT_NULL && stmt.data.none == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static token tok;
|
static token tok;
|
||||||
|
|
||||||
#ifdef __HOST
|
#ifdef __HOST
|
||||||
@@ -251,7 +250,7 @@ parse_formal_parameter_list (void)
|
|||||||
lexer_save_token (tok);
|
lexer_save_token (tok);
|
||||||
|
|
||||||
if (i != MAX_PARAMS - 1)
|
if (i != MAX_PARAMS - 1)
|
||||||
res.names[i + 1] = NULL;
|
res.names[i + 1] = null_string;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,7 +305,7 @@ parse_function_expression (void)
|
|||||||
skip_newlines ();
|
skip_newlines ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
res.name = NULL;
|
res.name = null_string;
|
||||||
|
|
||||||
current_token_must_be (TOK_OPEN_PAREN);
|
current_token_must_be (TOK_OPEN_PAREN);
|
||||||
|
|
||||||
@@ -557,7 +556,7 @@ parse_assigment_expression (void)
|
|||||||
{
|
{
|
||||||
.oper = AO_NONE,
|
.oper = AO_NONE,
|
||||||
.type = ET_CALL,
|
.type = ET_CALL,
|
||||||
.var = NULL,
|
.var = null_string,
|
||||||
.data.call_expr = parse_call_expression ()
|
.data.call_expr = parse_call_expression ()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -608,7 +607,7 @@ parse_assigment_expression (void)
|
|||||||
default:
|
default:
|
||||||
res.oper = AO_NONE;
|
res.oper = AO_NONE;
|
||||||
res.data.ops.op1 = (operand) { .is_literal = false, .data.name = res.var };
|
res.data.ops.op1 = (operand) { .is_literal = false, .data.name = res.var };
|
||||||
res.var = NULL;
|
res.var = null_string;
|
||||||
goto parse_operator;
|
goto parse_operator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1039,7 +1038,7 @@ parse_expression_inside_parens (statement *res)
|
|||||||
{
|
{
|
||||||
token_after_newlines_must_be (TOK_OPEN_PAREN);
|
token_after_newlines_must_be (TOK_OPEN_PAREN);
|
||||||
skip_newlines ();
|
skip_newlines ();
|
||||||
res->data.expr = parse_expression ();
|
res->data.expr = parse_assigment_expression ();
|
||||||
token_after_newlines_must_be (TOK_CLOSE_PAREN);
|
token_after_newlines_must_be (TOK_CLOSE_PAREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1116,6 +1115,37 @@ parser_parse_statement (void)
|
|||||||
|
|
||||||
skip_newlines ();
|
skip_newlines ();
|
||||||
|
|
||||||
|
if (current_scopes[scope_index - 1].was_stmt
|
||||||
|
&& (current_scopes[scope_index - 1].type
|
||||||
|
& (SCOPE_IF | SCOPE_WITH | SCOPE_SWITCH | SCOPE_ELSE | SCOPE_CATCH
|
||||||
|
| SCOPE_FUNCTION | SCOPE_WHILE | SCOPE_FOR)))
|
||||||
|
{
|
||||||
|
uint32_t type = current_scopes[scope_index - 1].type;
|
||||||
|
pop_scope ();
|
||||||
|
|
||||||
|
lexer_save_token (tok);
|
||||||
|
|
||||||
|
if (type & SCOPE_IF && !is_keyword (KW_ELSE))
|
||||||
|
return (statement) { .type = STMT_END_IF, .data.none = NULL };
|
||||||
|
if (type & SCOPE_WITH)
|
||||||
|
return (statement) { .type = STMT_END_WITH, .data.none = NULL };
|
||||||
|
if (type & SCOPE_SWITCH)
|
||||||
|
return (statement) { .type = STMT_END_SWITCH, .data.none = NULL };
|
||||||
|
if (type & SCOPE_ELSE)
|
||||||
|
return (statement) { .type = STMT_END_IF, .data.none = NULL };
|
||||||
|
if (type & SCOPE_CATCH && !is_keyword (KW_FINALLY))
|
||||||
|
return (statement) { .type = STMT_END_CATCH, .data.none = NULL };
|
||||||
|
if (type & SCOPE_CATCH)
|
||||||
|
return (statement) { .type = STMT_END_FINALLY, .data.none = NULL };
|
||||||
|
if (type & SCOPE_FUNCTION)
|
||||||
|
return (statement) { .type = STMT_END_FUNCTION, .data.none = NULL };
|
||||||
|
if (type & SCOPE_WHILE)
|
||||||
|
return (statement) { .type = STMT_END_WHILE, .data.none = NULL };
|
||||||
|
if (type & SCOPE_FOR)
|
||||||
|
return (statement) { .type = STMT_END_FOR_OR_FOR_IN, .data.none = NULL };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (is_keyword (KW_FINALLY))
|
if (is_keyword (KW_FINALLY))
|
||||||
{
|
{
|
||||||
res.type = STMT_FINALLY;
|
res.type = STMT_FINALLY;
|
||||||
@@ -1125,12 +1155,6 @@ parser_parse_statement (void)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_scopes[scope_index - 1].was_stmt
|
|
||||||
&& (current_scopes[scope_index - 1].type & (SCOPE_IF | SCOPE_DO | SCOPE_WITH | SCOPE_SWITCH | SCOPE_ELSE
|
|
||||||
| SCOPE_CATCH | SCOPE_FINALLY | SCOPE_FUNCTION | SCOPE_WHILE
|
|
||||||
| SCOPE_FOR)))
|
|
||||||
pop_scope ();
|
|
||||||
|
|
||||||
current_scopes[scope_index - 1].was_stmt = true;
|
current_scopes[scope_index - 1].was_stmt = true;
|
||||||
|
|
||||||
if (tok.type == TOK_EOF)
|
if (tok.type == TOK_EOF)
|
||||||
@@ -1144,27 +1168,25 @@ parser_parse_statement (void)
|
|||||||
{
|
{
|
||||||
if (tok.type == TOK_CLOSE_PAREN)
|
if (tok.type == TOK_CLOSE_PAREN)
|
||||||
{
|
{
|
||||||
res.type = STMT_SUBEXPRESSION_END;
|
res.type = STMT_END_SUBEXPRESSION;
|
||||||
pop_scope ();
|
pop_scope ();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
res.type = STMT_EXPRESSION;
|
res.type = STMT_EXPRESSION;
|
||||||
res.data.expr = parse_expression ();
|
res.data.expr = parse_assigment_expression ();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if (tok.type == TOK_OPEN_BRACE)
|
if (tok.type == TOK_OPEN_BRACE)
|
||||||
{
|
{
|
||||||
res.type = STMT_BLOCK_START;
|
|
||||||
push_scope (SCOPE_BLOCK);
|
push_scope (SCOPE_BLOCK);
|
||||||
return res;
|
return parser_parse_statement ();
|
||||||
}
|
}
|
||||||
if (tok.type == TOK_CLOSE_BRACE)
|
if (tok.type == TOK_CLOSE_BRACE)
|
||||||
{
|
{
|
||||||
current_scope_must_be (SCOPE_BLOCK);
|
current_scope_must_be (SCOPE_BLOCK);
|
||||||
res.type = STMT_BLOCK_END;
|
|
||||||
pop_scope ();
|
pop_scope ();
|
||||||
current_scopes[scope_index - 1].was_stmt = true;
|
current_scopes[scope_index - 1].was_stmt = true;
|
||||||
return res;
|
return parser_parse_statement ();
|
||||||
}
|
}
|
||||||
if (is_keyword (KW_ELSE))
|
if (is_keyword (KW_ELSE))
|
||||||
{
|
{
|
||||||
@@ -1193,6 +1215,7 @@ parser_parse_statement (void)
|
|||||||
{
|
{
|
||||||
insert_semicolon ();
|
insert_semicolon ();
|
||||||
pop_scope ();
|
pop_scope ();
|
||||||
|
res.type = STMT_END_DO_WHILE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
push_scope (SCOPE_WHILE);
|
push_scope (SCOPE_WHILE);
|
||||||
@@ -1236,7 +1259,7 @@ parser_parse_statement (void)
|
|||||||
}
|
}
|
||||||
if (is_keyword (KW_DO))
|
if (is_keyword (KW_DO))
|
||||||
{
|
{
|
||||||
res.type = STMT_DO;
|
res.type = STMT_DO_WHILE;
|
||||||
push_scope (SCOPE_DO);
|
push_scope (SCOPE_DO);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -1283,7 +1306,7 @@ parser_parse_statement (void)
|
|||||||
if (tok.type != TOK_SEMICOLON && tok.type != TOK_NEWLINE)
|
if (tok.type != TOK_SEMICOLON && tok.type != TOK_NEWLINE)
|
||||||
{
|
{
|
||||||
unsigned int current_scope_index = scope_index;
|
unsigned int current_scope_index = scope_index;
|
||||||
res.data.expr = parse_expression ();
|
res.data.expr = parse_assigment_expression ();
|
||||||
if (current_scope_index == scope_index)
|
if (current_scope_index == scope_index)
|
||||||
insert_semicolon ();
|
insert_semicolon ();
|
||||||
}
|
}
|
||||||
@@ -1308,7 +1331,7 @@ parser_parse_statement (void)
|
|||||||
{
|
{
|
||||||
res.type = STMT_THROW;
|
res.type = STMT_THROW;
|
||||||
tok = lexer_next_token ();
|
tok = lexer_next_token ();
|
||||||
res.data.expr = parse_expression ();
|
res.data.expr = parse_assigment_expression ();
|
||||||
insert_semicolon ();
|
insert_semicolon ();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -1324,7 +1347,7 @@ parser_parse_statement (void)
|
|||||||
pop_scope ();
|
pop_scope ();
|
||||||
current_scope_must_be (SCOPE_SWITCH);
|
current_scope_must_be (SCOPE_SWITCH);
|
||||||
skip_newlines ();
|
skip_newlines ();
|
||||||
res.data.expr = parse_expression ();
|
res.data.expr = parse_assigment_expression ();
|
||||||
token_after_newlines_must_be (TOK_SEMICOLON);
|
token_after_newlines_must_be (TOK_SEMICOLON);
|
||||||
push_scope (SCOPE_CASE);
|
push_scope (SCOPE_CASE);
|
||||||
return res;
|
return res;
|
||||||
@@ -1352,15 +1375,15 @@ parser_parse_statement (void)
|
|||||||
{
|
{
|
||||||
lexer_save_token (tok);
|
lexer_save_token (tok);
|
||||||
tok = saved;
|
tok = saved;
|
||||||
expression expr = parse_expression ();
|
assignment_expression expr = parse_assigment_expression ();
|
||||||
res.type = STMT_EXPRESSION;
|
res.type = STMT_EXPRESSION;
|
||||||
res.data.expr = expr;
|
res.data.expr = expr;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expression expr = parse_expression ();
|
assignment_expression expr = parse_assigment_expression ();
|
||||||
if (!is_expression_empty (expr.exprs[0]))
|
if (!is_expression_empty (expr))
|
||||||
{
|
{
|
||||||
res.type = STMT_EXPRESSION;
|
res.type = STMT_EXPRESSION;
|
||||||
res.data.expr = expr;
|
res.data.expr = expr;
|
||||||
|
|||||||
+26
-24
@@ -18,12 +18,7 @@
|
|||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
struct source_element_list;
|
#define null_string 255
|
||||||
struct statement_list;
|
|
||||||
struct statement;
|
|
||||||
struct assignment_expression;
|
|
||||||
struct member_expression;
|
|
||||||
|
|
||||||
#define MAX_PARAMS 5
|
#define MAX_PARAMS 5
|
||||||
#define MAX_EXPRS 2
|
#define MAX_EXPRS 2
|
||||||
#define MAX_PROPERTIES 5
|
#define MAX_PROPERTIES 5
|
||||||
@@ -34,14 +29,14 @@ struct member_expression;
|
|||||||
typedef struct formal_parameter_list
|
typedef struct formal_parameter_list
|
||||||
{
|
{
|
||||||
/** Identifiers of a parameter. Next after last parameter is NULL. */
|
/** Identifiers of a parameter. Next after last parameter is NULL. */
|
||||||
const char *names[MAX_PARAMS];
|
uint8_t names[MAX_PARAMS];
|
||||||
}
|
}
|
||||||
formal_parameter_list;
|
formal_parameter_list;
|
||||||
|
|
||||||
static const formal_parameter_list
|
static const formal_parameter_list
|
||||||
empty_formal_parameter_list =
|
empty_formal_parameter_list =
|
||||||
{
|
{
|
||||||
.names = { [0] = NULL }
|
.names = { [0] = null_string }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool is_formal_parameter_list_empty (formal_parameter_list);
|
bool is_formal_parameter_list_empty (formal_parameter_list);
|
||||||
@@ -51,7 +46,7 @@ bool is_formal_parameter_list_empty (formal_parameter_list);
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/** Identifier: name of a function. Can be NULL for anonimous functions. */
|
/** Identifier: name of a function. Can be NULL for anonimous functions. */
|
||||||
const char *name;
|
uint8_t name;
|
||||||
/** List of parameter of a function. Can be NULL. */
|
/** List of parameter of a function. Can be NULL. */
|
||||||
formal_parameter_list params;
|
formal_parameter_list params;
|
||||||
}
|
}
|
||||||
@@ -82,7 +77,7 @@ typedef struct
|
|||||||
/** Used by null literal, always NULL. */
|
/** Used by null literal, always NULL. */
|
||||||
void *none;
|
void *none;
|
||||||
/** String literal value. */
|
/** String literal value. */
|
||||||
const char *str;
|
uint8_t str;
|
||||||
/** Number value. */
|
/** Number value. */
|
||||||
int num;
|
int num;
|
||||||
/** Boolean value. */
|
/** Boolean value. */
|
||||||
@@ -100,7 +95,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
void *none;
|
void *none;
|
||||||
literal lit;
|
literal lit;
|
||||||
const char *name;
|
uint8_t name;
|
||||||
}
|
}
|
||||||
data;
|
data;
|
||||||
}
|
}
|
||||||
@@ -142,7 +137,7 @@ typedef operand_list argument_list;
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char *name;
|
uint8_t name;
|
||||||
argument_list args;
|
argument_list args;
|
||||||
}
|
}
|
||||||
call_expression;
|
call_expression;
|
||||||
@@ -262,7 +257,7 @@ typedef struct
|
|||||||
expression_type type;
|
expression_type type;
|
||||||
|
|
||||||
/** NUllable. */
|
/** NUllable. */
|
||||||
const char *var;
|
uint8_t var;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
@@ -302,7 +297,7 @@ typedef expression_list expression;
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char *name;
|
uint8_t name;
|
||||||
assignment_expression assign_expr;
|
assignment_expression assign_expr;
|
||||||
}
|
}
|
||||||
variable_declaration;
|
variable_declaration;
|
||||||
@@ -310,7 +305,7 @@ variable_declaration;
|
|||||||
static const variable_declaration
|
static const variable_declaration
|
||||||
empty_variable_declaration =
|
empty_variable_declaration =
|
||||||
{
|
{
|
||||||
.name = NULL,
|
.name = null_string,
|
||||||
.assign_expr = { .oper = AO_NONE, .type = ET_NONE, .data.none = NULL }
|
.assign_expr = { .oper = AO_NONE, .type = ET_NONE, .data.none = NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -378,33 +373,40 @@ for_or_for_in_statement;
|
|||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
STMT_NULL,
|
STMT_NULL,
|
||||||
STMT_BLOCK_START,
|
|
||||||
STMT_BLOCK_END,
|
|
||||||
STMT_VARIABLE,
|
STMT_VARIABLE,
|
||||||
STMT_EMPTY,
|
STMT_EMPTY,
|
||||||
STMT_IF,
|
STMT_IF,
|
||||||
STMT_ELSE,
|
STMT_ELSE,
|
||||||
STMT_ELSE_IF,
|
STMT_ELSE_IF,
|
||||||
STMT_DO,
|
STMT_END_IF,
|
||||||
|
STMT_DO_WHILE,
|
||||||
|
STMT_END_DO_WHILE,
|
||||||
STMT_WHILE,
|
STMT_WHILE,
|
||||||
|
|
||||||
|
STMT_END_WHILE,
|
||||||
STMT_FOR_OR_FOR_IN,
|
STMT_FOR_OR_FOR_IN,
|
||||||
|
STMT_END_FOR_OR_FOR_IN,
|
||||||
STMT_CONTINUE,
|
STMT_CONTINUE,
|
||||||
STMT_BREAK,
|
STMT_BREAK,
|
||||||
|
|
||||||
STMT_RETURN,
|
STMT_RETURN,
|
||||||
STMT_WITH,
|
STMT_WITH,
|
||||||
|
STMT_END_WITH,
|
||||||
STMT_LABELLED,
|
STMT_LABELLED,
|
||||||
STMT_SWITCH,
|
STMT_SWITCH,
|
||||||
|
|
||||||
|
STMT_END_SWITCH,
|
||||||
STMT_CASE,
|
STMT_CASE,
|
||||||
STMT_THROW,
|
STMT_THROW,
|
||||||
|
|
||||||
STMT_TRY,
|
STMT_TRY,
|
||||||
STMT_CATCH,
|
STMT_CATCH,
|
||||||
|
STMT_END_CATCH,
|
||||||
STMT_FINALLY,
|
STMT_FINALLY,
|
||||||
|
STMT_END_FINALLY,
|
||||||
STMT_EXPRESSION,
|
STMT_EXPRESSION,
|
||||||
STMT_SUBEXPRESSION_END,
|
STMT_END_SUBEXPRESSION,
|
||||||
|
|
||||||
STMT_FUNCTION,
|
STMT_FUNCTION,
|
||||||
|
STMT_END_FUNCTION,
|
||||||
STMT_EOF
|
STMT_EOF
|
||||||
}
|
}
|
||||||
statement_type;
|
statement_type;
|
||||||
@@ -417,9 +419,9 @@ typedef struct statement
|
|||||||
{
|
{
|
||||||
void *none;
|
void *none;
|
||||||
variable_declaration_list var_stmt;
|
variable_declaration_list var_stmt;
|
||||||
expression expr;
|
assignment_expression expr;
|
||||||
for_or_for_in_statement for_stmt;
|
for_or_for_in_statement for_stmt;
|
||||||
const char *name;
|
uint8_t name;
|
||||||
function_declaration fun_decl;
|
function_declaration fun_decl;
|
||||||
}
|
}
|
||||||
data;
|
data;
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ __strtof (const char *nptr, char **endptr)
|
|||||||
(void) endptr;
|
(void) endptr;
|
||||||
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
JERRY_UNIMPLEMENTED ();
|
||||||
}
|
} /* __strtof */
|
||||||
|
|
||||||
/** Calculate the length of a string. */
|
/** Calculate the length of a string. */
|
||||||
size_t
|
size_t
|
||||||
|
|||||||
@@ -44,11 +44,12 @@ extern int __isalpha (int);
|
|||||||
extern int __isdigit (int);
|
extern int __isdigit (int);
|
||||||
extern int __isxdigit (int);
|
extern int __isxdigit (int);
|
||||||
|
|
||||||
extern FILE* __fopen(const char *path, const char *mode);
|
extern FILE* __fopen(const char *, const char *);
|
||||||
extern int __fclose(FILE *fp);
|
extern int __fclose(FILE *);
|
||||||
extern size_t __fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
extern void __rewind(FILE *);
|
||||||
extern size_t __fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
|
extern size_t __fread(void *, size_t, size_t, FILE *);
|
||||||
extern int __fprintf(FILE *stream, const char *format, ...);
|
extern size_t __fwrite(const void *, size_t, size_t, FILE *);
|
||||||
|
extern int __fprintf(FILE *, const char *, ...);
|
||||||
|
|
||||||
#define DBL_MANT_DIG ( 52)
|
#define DBL_MANT_DIG ( 52)
|
||||||
#define DBL_DIG ( 10)
|
#define DBL_DIG ( 10)
|
||||||
|
|||||||
@@ -17,15 +17,12 @@
|
|||||||
#include "pretty-printer.h"
|
#include "pretty-printer.h"
|
||||||
|
|
||||||
static int intendation;
|
static int intendation;
|
||||||
static bool was_function_expression;
|
|
||||||
static bool was_subexpression;
|
|
||||||
|
|
||||||
static statement_type prev_stmt;
|
#define MAX_NAMES 100
|
||||||
|
|
||||||
void
|
void
|
||||||
pp_reset (void)
|
pp_reset (void)
|
||||||
{
|
{
|
||||||
prev_stmt = STMT_EOF;
|
|
||||||
intendation = 0;
|
intendation = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +36,7 @@ pp_token (token tok)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_STRING:
|
case TOK_STRING:
|
||||||
__printf ("STRING (%s)\n", tok.data.str);
|
__printf ("STRING (n%d)\n", tok.data.str);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_KEYWORD:
|
case TOK_KEYWORD:
|
||||||
@@ -417,11 +414,11 @@ pp_formal_parameter_list (formal_parameter_list param_list)
|
|||||||
|
|
||||||
for (i = 0; i < MAX_PARAMS; i++)
|
for (i = 0; i < MAX_PARAMS; i++)
|
||||||
{
|
{
|
||||||
if (param_list.names[i] == NULL)
|
if (param_list.names[i] == null_string)
|
||||||
break;
|
break;
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
__printf (", ");
|
__printf (", ");
|
||||||
__printf ("%s", param_list.names[i]);
|
__printf ("%s", lexer_get_string_by_id (param_list.names[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,11 +427,10 @@ pp_function_declaration (function_declaration func_decl)
|
|||||||
{
|
{
|
||||||
__printf ("function ");
|
__printf ("function ");
|
||||||
if (func_decl.name)
|
if (func_decl.name)
|
||||||
__printf ("%s ", func_decl.name);
|
__printf ("%s ", lexer_get_string_by_id (func_decl.name));
|
||||||
__putchar ('(');
|
__putchar ('(');
|
||||||
pp_formal_parameter_list (func_decl.params);
|
pp_formal_parameter_list (func_decl.params);
|
||||||
__printf (") ");
|
__printf (") ");
|
||||||
was_function_expression = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -470,7 +466,7 @@ pp_operand (operand op)
|
|||||||
if (op.is_literal)
|
if (op.is_literal)
|
||||||
pp_literal (op.data.lit);
|
pp_literal (op.data.lit);
|
||||||
else
|
else
|
||||||
__printf ("%s", op.data.name);
|
__printf ("%s", lexer_get_string_by_id (op.data.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -515,8 +511,8 @@ pp_property_list (property_list prop_list)
|
|||||||
static void
|
static void
|
||||||
pp_call_expression (call_expression expr)
|
pp_call_expression (call_expression expr)
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (expr.name);
|
JERRY_ASSERT (expr.name < MAX_NAMES);
|
||||||
__printf ("%s (", expr.name);
|
__printf ("%s (", lexer_get_string_by_id (expr.name));
|
||||||
pp_operand_list (expr.args);
|
pp_operand_list (expr.args);
|
||||||
__printf (")\n");
|
__printf (")\n");
|
||||||
}
|
}
|
||||||
@@ -832,18 +828,12 @@ pp_expression (expression_list expr_list)
|
|||||||
__printf (", ");
|
__printf (", ");
|
||||||
pp_assignment_expression (expr_list.exprs[i]);
|
pp_assignment_expression (expr_list.exprs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (was_subexpression && !was_function_expression)
|
|
||||||
{
|
|
||||||
__putchar (')');
|
|
||||||
was_subexpression = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pp_variable_declaration (variable_declaration var_decl)
|
pp_variable_declaration (variable_declaration var_decl)
|
||||||
{
|
{
|
||||||
__printf ("%s", var_decl.name);
|
__printf ("%s", lexer_get_string_by_id (var_decl.name));
|
||||||
if (!is_expression_empty (var_decl.assign_expr))
|
if (!is_expression_empty (var_decl.assign_expr))
|
||||||
{
|
{
|
||||||
__printf (" = ");
|
__printf (" = ");
|
||||||
@@ -925,32 +915,9 @@ pp_for_or_for_in_statement (for_or_for_in_statement for_or_for_in_stmt)
|
|||||||
void
|
void
|
||||||
pp_statement (statement stmt)
|
pp_statement (statement stmt)
|
||||||
{
|
{
|
||||||
was_function_expression = false;
|
|
||||||
was_subexpression = false;
|
|
||||||
|
|
||||||
if (prev_stmt == STMT_BLOCK_END)
|
|
||||||
{
|
|
||||||
if (stmt.type == STMT_EMPTY)
|
|
||||||
{
|
|
||||||
__printf (";\n");
|
|
||||||
prev_stmt = stmt.type;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
__putchar ('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (stmt.type)
|
switch (stmt.type)
|
||||||
{
|
{
|
||||||
case STMT_BLOCK_START:
|
case STMT_EMPTY:
|
||||||
__printf ("{\n");
|
|
||||||
intendation += 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STMT_BLOCK_END:
|
|
||||||
intendation -= 2;
|
|
||||||
intend ();
|
|
||||||
__printf ("}");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_VARIABLE:
|
case STMT_VARIABLE:
|
||||||
@@ -958,44 +925,67 @@ pp_statement (statement stmt)
|
|||||||
pp_variable_declaration_list (stmt.data.var_stmt);
|
pp_variable_declaration_list (stmt.data.var_stmt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_EMPTY:
|
|
||||||
__printf (";\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STMT_IF:
|
case STMT_IF:
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("if (");
|
__printf ("if (");
|
||||||
pp_expression (stmt.data.expr);
|
pp_assignment_expression (stmt.data.expr);
|
||||||
__printf (") ");
|
__printf (") {\n");
|
||||||
|
intendation += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_ELSE:
|
case STMT_ELSE:
|
||||||
|
intendation -= 2;
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("else ");
|
__printf ("} else {\n");
|
||||||
|
intendation += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_ELSE_IF:
|
case STMT_ELSE_IF:
|
||||||
|
intendation -= 2;
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("else if(");
|
__printf ("} else if(");
|
||||||
pp_expression (stmt.data.expr);
|
pp_assignment_expression (stmt.data.expr);
|
||||||
__printf (") ");
|
__printf (") {\n");
|
||||||
|
intendation += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_DO:
|
case STMT_END_IF:
|
||||||
|
case STMT_END_WHILE:
|
||||||
|
case STMT_END_WITH:
|
||||||
|
case STMT_END_SWITCH:
|
||||||
|
case STMT_END_CATCH:
|
||||||
|
case STMT_END_FINALLY:
|
||||||
|
case STMT_END_FUNCTION:
|
||||||
|
intendation -= 2;
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("do ");
|
__printf ("}\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case STMT_DO_WHILE:
|
||||||
|
intend ();
|
||||||
|
__printf ("do {");
|
||||||
|
intendation += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STMT_END_DO_WHILE:
|
||||||
|
intendation -= 2;
|
||||||
|
intend ();
|
||||||
|
__printf ("} while (");
|
||||||
|
pp_assignment_expression (stmt.data.expr);
|
||||||
|
__printf (");\n");
|
||||||
|
|
||||||
case STMT_WHILE:
|
case STMT_WHILE:
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("while (");
|
__printf ("while (");
|
||||||
pp_expression (stmt.data.expr);
|
pp_assignment_expression (stmt.data.expr);
|
||||||
__printf (") ");
|
__printf (") {\n");
|
||||||
|
intendation += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_FOR_OR_FOR_IN:
|
case STMT_FOR_OR_FOR_IN:
|
||||||
intend ();
|
intend ();
|
||||||
pp_for_or_for_in_statement (stmt.data.for_stmt);
|
pp_for_or_for_in_statement (stmt.data.for_stmt);
|
||||||
|
intendation += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_CONTINUE:
|
case STMT_CONTINUE:
|
||||||
@@ -1011,16 +1001,15 @@ pp_statement (statement stmt)
|
|||||||
case STMT_RETURN:
|
case STMT_RETURN:
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("return ");
|
__printf ("return ");
|
||||||
pp_expression (stmt.data.expr);
|
pp_assignment_expression (stmt.data.expr);
|
||||||
if (!was_function_expression)
|
|
||||||
__printf (";\n");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_WITH:
|
case STMT_WITH:
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("with (");
|
__printf ("with (");
|
||||||
pp_expression (stmt.data.expr);
|
pp_assignment_expression (stmt.data.expr);
|
||||||
__printf (") ");
|
__printf (") ");
|
||||||
|
intendation += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_LABELLED:
|
case STMT_LABELLED:
|
||||||
@@ -1031,21 +1020,22 @@ pp_statement (statement stmt)
|
|||||||
case STMT_SWITCH:
|
case STMT_SWITCH:
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("switch (");
|
__printf ("switch (");
|
||||||
pp_expression (stmt.data.expr);
|
pp_assignment_expression (stmt.data.expr);
|
||||||
__printf (") ");
|
__printf (") ");
|
||||||
|
intendation += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_CASE:
|
case STMT_CASE:
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("case ");
|
__printf ("case ");
|
||||||
pp_expression (stmt.data.expr);
|
pp_assignment_expression (stmt.data.expr);
|
||||||
__printf (":\n");
|
__printf (":\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_THROW:
|
case STMT_THROW:
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("throw ");
|
__printf ("throw ");
|
||||||
pp_expression (stmt.data.expr);
|
pp_assignment_expression (stmt.data.expr);
|
||||||
__printf (";\n");
|
__printf (";\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1057,38 +1047,34 @@ pp_statement (statement stmt)
|
|||||||
case STMT_CATCH:
|
case STMT_CATCH:
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("catch (");
|
__printf ("catch (");
|
||||||
pp_expression (stmt.data.expr);
|
pp_assignment_expression (stmt.data.expr);
|
||||||
__printf (") ");
|
__printf (") ");
|
||||||
|
intendation += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_FINALLY:
|
case STMT_FINALLY:
|
||||||
intend ();
|
intend ();
|
||||||
__printf ("finally ");
|
__printf ("finally ");
|
||||||
|
intendation += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_EXPRESSION:
|
case STMT_EXPRESSION:
|
||||||
intend ();
|
intend ();
|
||||||
pp_expression (stmt.data.expr);
|
pp_assignment_expression (stmt.data.expr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_SUBEXPRESSION_END:
|
case STMT_END_SUBEXPRESSION:
|
||||||
__putchar (')');
|
__putchar (')');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_FUNCTION:
|
case STMT_FUNCTION:
|
||||||
intend ();
|
intend ();
|
||||||
pp_function_declaration (stmt.data.fun_decl);
|
pp_function_declaration (stmt.data.fun_decl);
|
||||||
|
__printf ("{\n");
|
||||||
|
intendation += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
JERRY_UNREACHABLE ();
|
JERRY_UNREACHABLE ();
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_stmt = stmt.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pp_finish (void)
|
|
||||||
{
|
|
||||||
if (prev_stmt == STMT_BLOCK_END)
|
|
||||||
__putchar ('\n');
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERIALIZER_H
|
||||||
|
#define SERIALIZER_H
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
void serializer_init (void);
|
||||||
|
|
||||||
|
void serializer_dump_data (const void *, size_t);
|
||||||
|
|
||||||
|
#endif // SERIALIZER_H
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
extern void __noreturn exit(int status);
|
extern void __noreturn exit(int status);
|
||||||
extern FILE* fopen(const char *path, const char *mode);
|
extern FILE* fopen(const char *path, const char *mode);
|
||||||
extern int fclose(FILE *fp);
|
extern int fclose(FILE *fp);
|
||||||
|
extern int rewind (FILE *);
|
||||||
extern size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
extern size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||||
extern size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
|
extern size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||||
extern int vprintf (__const char *__restrict __format, __builtin_va_list __arg);
|
extern int vprintf (__const char *__restrict __format, __builtin_va_list __arg);
|
||||||
@@ -78,6 +79,14 @@ __fopen(const char *path, /**< file path */
|
|||||||
return fopen( path, mode);
|
return fopen( path, mode);
|
||||||
} /* __fopen */
|
} /* __fopen */
|
||||||
|
|
||||||
|
/** The rewind() function sets the file position
|
||||||
|
indicator for the stream pointed to by STREAM to the beginning of the file. */
|
||||||
|
void
|
||||||
|
__rewind (FILE *stream)
|
||||||
|
{
|
||||||
|
rewind (stream);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fclose
|
* fclose
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "serializer.h"
|
||||||
|
#include "jerry-libc.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
serializer_init (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serializer_dump_data (const void *data, size_t size)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
__putchar (((char *) data)[i]);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
TODO (Dump memory)
|
||||||
+69
-13
@@ -31,6 +31,13 @@
|
|||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "pretty-printer.h"
|
#include "pretty-printer.h"
|
||||||
|
#include "bytecode-generator.h"
|
||||||
|
|
||||||
|
#define DUMP_TOKENS (1u << 0)
|
||||||
|
#define DUMP_AST (1u << 1)
|
||||||
|
#define DUMP_BYTECODE (1u << 2)
|
||||||
|
|
||||||
|
#define MAX_STRINGS 100
|
||||||
|
|
||||||
void fake_exit (void);
|
void fake_exit (void);
|
||||||
|
|
||||||
@@ -85,12 +92,27 @@ fake_exit (void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
check_for_several_dumps (uint8_t dump)
|
||||||
|
{
|
||||||
|
bool was_bit = 0;
|
||||||
|
for (; dump; dump >>= 1)
|
||||||
|
{
|
||||||
|
if (dump & 1u)
|
||||||
|
{
|
||||||
|
if (was_bit)
|
||||||
|
jerry_Exit (ERR_SEVERAL_FILES);
|
||||||
|
else
|
||||||
|
was_bit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
statement st;
|
statement st;
|
||||||
bool dump_tokens = false;
|
uint8_t dump = 0;
|
||||||
bool dump_ast = false;
|
|
||||||
const char *file_name = NULL;
|
const char *file_name = NULL;
|
||||||
#ifdef __HOST
|
#ifdef __HOST
|
||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
@@ -102,25 +124,26 @@ main (int argc, char **argv)
|
|||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
if (!__strcmp ("-t", argv[i]))
|
if (!__strcmp ("-t", argv[i]))
|
||||||
dump_tokens = true;
|
dump |= DUMP_TOKENS;
|
||||||
else if (!__strcmp ("-a", argv[i]))
|
else if (!__strcmp ("-a", argv[i]))
|
||||||
dump_ast = true;
|
dump |= DUMP_AST;
|
||||||
|
else if (!__strcmp ("-b", argv[i]))
|
||||||
|
dump |= DUMP_BYTECODE;
|
||||||
else if (file_name == NULL)
|
else if (file_name == NULL)
|
||||||
file_name = argv[i];
|
file_name = argv[i];
|
||||||
else
|
else
|
||||||
jerry_Exit (ERR_SEVERAL_FILES);
|
jerry_Exit (ERR_SEVERAL_FILES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_for_several_dumps (dump);
|
||||||
|
|
||||||
|
if (!dump)
|
||||||
|
dump |= DUMP_BYTECODE;
|
||||||
|
|
||||||
|
#ifdef __HOST
|
||||||
if (file_name == NULL)
|
if (file_name == NULL)
|
||||||
jerry_Exit (ERR_NO_FILES);
|
jerry_Exit (ERR_NO_FILES);
|
||||||
|
|
||||||
if (dump_tokens && dump_ast)
|
|
||||||
jerry_Exit (ERR_SEVERAL_FILES);
|
|
||||||
|
|
||||||
if (!dump_tokens)
|
|
||||||
dump_ast = true;
|
|
||||||
|
|
||||||
#ifdef __HOST
|
|
||||||
file = __fopen (file_name, "r");
|
file = __fopen (file_name, "r");
|
||||||
|
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
@@ -133,7 +156,7 @@ main (int argc, char **argv)
|
|||||||
lexer_set_source (generated_source);
|
lexer_set_source (generated_source);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (dump_ast)
|
if (dump & DUMP_AST)
|
||||||
{
|
{
|
||||||
parser_init ();
|
parser_init ();
|
||||||
st = parser_parse_statement ();
|
st = parser_parse_statement ();
|
||||||
@@ -146,7 +169,7 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dump_tokens)
|
if (dump & DUMP_TOKENS)
|
||||||
{
|
{
|
||||||
token tok = lexer_next_token ();
|
token tok = lexer_next_token ();
|
||||||
while (tok.type != TOK_EOF)
|
while (tok.type != TOK_EOF)
|
||||||
@@ -156,6 +179,39 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dump & DUMP_BYTECODE)
|
||||||
|
{
|
||||||
|
const char *strings[MAX_STRINGS];
|
||||||
|
uint8_t strings_num;
|
||||||
|
// First run parser to fill list of strings
|
||||||
|
token tok = lexer_next_token ();
|
||||||
|
while (tok.type != TOK_EOF)
|
||||||
|
tok = lexer_next_token ();
|
||||||
|
|
||||||
|
strings_num = lexer_get_strings (strings);
|
||||||
|
|
||||||
|
// Reset lexer
|
||||||
|
#ifdef __HOST
|
||||||
|
__rewind (file);
|
||||||
|
lexer_set_file (file);
|
||||||
|
#else
|
||||||
|
lexer_set_source (generated_source);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
parser_init ();
|
||||||
|
generator_init ();
|
||||||
|
generator_dump_strings (strings, strings_num);
|
||||||
|
st = parser_parse_statement ();
|
||||||
|
JERRY_ASSERT (!is_statement_null (st));
|
||||||
|
__printf (" ST_TYPE = %d", st.type == STMT_EOF);
|
||||||
|
while (st.type != STMT_EOF)
|
||||||
|
{
|
||||||
|
generator_dump_statement (st);
|
||||||
|
st = parser_parse_statement ();
|
||||||
|
JERRY_ASSERT (!is_statement_null (st));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//gen_bytecode (generated_source);
|
//gen_bytecode (generated_source);
|
||||||
//gen_bytecode ();
|
//gen_bytecode ();
|
||||||
//run_int ();
|
//run_int ();
|
||||||
|
|||||||
Reference in New Issue
Block a user