Add bytecode generator

This commit is contained in:
Ilmir Usmanov
2014-07-15 19:32:26 +04:00
parent 25ad63c9be
commit 0647cdd4f1
15 changed files with 467 additions and 151 deletions
+1 -1
View File
@@ -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
+113
View File
@@ -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++;
}
+25
View File
@@ -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
View File
@@ -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
+8 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+1 -1
View File
@@ -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
+6 -5
View File
@@ -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)
+61 -75
View File
@@ -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');
} }
+25
View File
@@ -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
+9
View File
@@ -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
* *
+31
View File
@@ -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
View File
@@ -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 ();