diff --git a/Makefile b/Makefile index cfac5dcb0..a484e178e 100644 --- a/Makefile +++ b/Makefile @@ -113,7 +113,7 @@ TARGET_MCU = -D__TARGET_MCU .PHONY: all debug debug.stdm32f4 release clean tests check install -all: clean debug release check +all: debug release debug.stdm32f4: clean debug.stdm32f4.bin diff --git a/src/libjsparser/bytecode-generator.c b/src/libjsparser/bytecode-generator.c new file mode 100644 index 000000000..b9ef5293e --- /dev/null +++ b/src/libjsparser/bytecode-generator.c @@ -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++; +} \ No newline at end of file diff --git a/src/libjsparser/bytecode-generator.h b/src/libjsparser/bytecode-generator.h new file mode 100644 index 000000000..4634decc2 --- /dev/null +++ b/src/libjsparser/bytecode-generator.h @@ -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 \ No newline at end of file diff --git a/src/libjsparser/lexer.c b/src/libjsparser/lexer.c index bbff2d4be..7c84370d6 100644 --- a/src/libjsparser/lexer.c +++ b/src/libjsparser/lexer.c @@ -81,7 +81,7 @@ static string_and_token keyword_tokens[] = #define MAX_NAMES 100 static string_and_token seen_names[MAX_NAMES]; -static size_t seen_names_num; +static uint8_t seen_names_num; static inline bool is_empty (token tok) @@ -210,9 +210,29 @@ add_to_seen_tokens (string_and_token snt) { JERRY_ASSERT (seen_names_num < MAX_NAMES); + snt.tok.data.name = (string_id) seen_names_num; 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 new_token (void) { @@ -318,7 +338,7 @@ parse_name (void) } 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 }); @@ -561,7 +581,7 @@ parse_string (void) // Eat up '"' 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 }); @@ -588,6 +608,7 @@ lexer_set_file (FILE *ex_file) file = ex_file; lexer_debug_log = __fopen ("lexer.log", "w"); saved_token = empty_token; + buffer = buffer_start = token_start = NULL; } #else void diff --git a/src/libjsparser/lexer.h b/src/libjsparser/lexer.h index 4c6c7a9f9..9203d3ab5 100644 --- a/src/libjsparser/lexer.h +++ b/src/libjsparser/lexer.h @@ -18,6 +18,8 @@ #include "globals.h" +typedef uint8_t string_id; + /* Keywords. */ typedef enum { @@ -141,11 +143,11 @@ typedef struct { void *none; keyword kw; - const char *name; + string_id name; bool is_true; int num; float fp_num; - const char *str; + string_id str; } data; } @@ -161,4 +163,8 @@ void lexer_save_token (token); void lexer_dump_buffer_state (void); +uint8_t lexer_get_strings (const char **); + +const char *lexer_get_string_by_id (string_id id); + #endif diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index afd6e1b24..d189d7eaa 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -20,7 +20,7 @@ bool is_formal_parameter_list_empty (formal_parameter_list list) { - return list.names[0] == NULL; + return list.names[0] == null_string; } bool @@ -56,7 +56,7 @@ is_expression_empty (assignment_expression expr) bool 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 @@ -65,7 +65,6 @@ is_statement_null (statement stmt) return stmt.type == STMT_NULL && stmt.data.none == NULL; } - static token tok; #ifdef __HOST @@ -251,7 +250,7 @@ parse_formal_parameter_list (void) lexer_save_token (tok); if (i != MAX_PARAMS - 1) - res.names[i + 1] = NULL; + res.names[i + 1] = null_string; break; } } @@ -306,7 +305,7 @@ parse_function_expression (void) skip_newlines (); } else - res.name = NULL; + res.name = null_string; current_token_must_be (TOK_OPEN_PAREN); @@ -557,7 +556,7 @@ parse_assigment_expression (void) { .oper = AO_NONE, .type = ET_CALL, - .var = NULL, + .var = null_string, .data.call_expr = parse_call_expression () }; } @@ -608,7 +607,7 @@ parse_assigment_expression (void) default: res.oper = AO_NONE; res.data.ops.op1 = (operand) { .is_literal = false, .data.name = res.var }; - res.var = NULL; + res.var = null_string; goto parse_operator; } @@ -1039,7 +1038,7 @@ parse_expression_inside_parens (statement *res) { token_after_newlines_must_be (TOK_OPEN_PAREN); skip_newlines (); - res->data.expr = parse_expression (); + res->data.expr = parse_assigment_expression (); token_after_newlines_must_be (TOK_CLOSE_PAREN); } @@ -1116,6 +1115,37 @@ parser_parse_statement (void) 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)) { res.type = STMT_FINALLY; @@ -1125,12 +1155,6 @@ parser_parse_statement (void) 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; if (tok.type == TOK_EOF) @@ -1144,27 +1168,25 @@ parser_parse_statement (void) { if (tok.type == TOK_CLOSE_PAREN) { - res.type = STMT_SUBEXPRESSION_END; + res.type = STMT_END_SUBEXPRESSION; pop_scope (); return res; } res.type = STMT_EXPRESSION; - res.data.expr = parse_expression (); + res.data.expr = parse_assigment_expression (); return res; } if (tok.type == TOK_OPEN_BRACE) { - res.type = STMT_BLOCK_START; push_scope (SCOPE_BLOCK); - return res; + return parser_parse_statement (); } if (tok.type == TOK_CLOSE_BRACE) { current_scope_must_be (SCOPE_BLOCK); - res.type = STMT_BLOCK_END; pop_scope (); current_scopes[scope_index - 1].was_stmt = true; - return res; + return parser_parse_statement (); } if (is_keyword (KW_ELSE)) { @@ -1193,6 +1215,7 @@ parser_parse_statement (void) { insert_semicolon (); pop_scope (); + res.type = STMT_END_DO_WHILE; } else push_scope (SCOPE_WHILE); @@ -1236,7 +1259,7 @@ parser_parse_statement (void) } if (is_keyword (KW_DO)) { - res.type = STMT_DO; + res.type = STMT_DO_WHILE; push_scope (SCOPE_DO); return res; } @@ -1283,7 +1306,7 @@ parser_parse_statement (void) if (tok.type != TOK_SEMICOLON && tok.type != TOK_NEWLINE) { unsigned int current_scope_index = scope_index; - res.data.expr = parse_expression (); + res.data.expr = parse_assigment_expression (); if (current_scope_index == scope_index) insert_semicolon (); } @@ -1308,7 +1331,7 @@ parser_parse_statement (void) { res.type = STMT_THROW; tok = lexer_next_token (); - res.data.expr = parse_expression (); + res.data.expr = parse_assigment_expression (); insert_semicolon (); return res; } @@ -1324,7 +1347,7 @@ parser_parse_statement (void) pop_scope (); current_scope_must_be (SCOPE_SWITCH); skip_newlines (); - res.data.expr = parse_expression (); + res.data.expr = parse_assigment_expression (); token_after_newlines_must_be (TOK_SEMICOLON); push_scope (SCOPE_CASE); return res; @@ -1352,15 +1375,15 @@ parser_parse_statement (void) { lexer_save_token (tok); tok = saved; - expression expr = parse_expression (); + assignment_expression expr = parse_assigment_expression (); res.type = STMT_EXPRESSION; res.data.expr = expr; return res; } } - expression expr = parse_expression (); - if (!is_expression_empty (expr.exprs[0])) + assignment_expression expr = parse_assigment_expression (); + if (!is_expression_empty (expr)) { res.type = STMT_EXPRESSION; res.data.expr = expr; diff --git a/src/libjsparser/parser.h b/src/libjsparser/parser.h index 62557cae6..43fec8c96 100644 --- a/src/libjsparser/parser.h +++ b/src/libjsparser/parser.h @@ -18,12 +18,7 @@ #include "globals.h" -struct source_element_list; -struct statement_list; -struct statement; -struct assignment_expression; -struct member_expression; - +#define null_string 255 #define MAX_PARAMS 5 #define MAX_EXPRS 2 #define MAX_PROPERTIES 5 @@ -34,14 +29,14 @@ struct member_expression; typedef struct formal_parameter_list { /** Identifiers of a parameter. Next after last parameter is NULL. */ - const char *names[MAX_PARAMS]; + uint8_t names[MAX_PARAMS]; } formal_parameter_list; static const formal_parameter_list empty_formal_parameter_list = { - .names = { [0] = NULL } + .names = { [0] = null_string } }; bool is_formal_parameter_list_empty (formal_parameter_list); @@ -51,7 +46,7 @@ bool is_formal_parameter_list_empty (formal_parameter_list); typedef struct { /** 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. */ formal_parameter_list params; } @@ -82,7 +77,7 @@ typedef struct /** Used by null literal, always NULL. */ void *none; /** String literal value. */ - const char *str; + uint8_t str; /** Number value. */ int num; /** Boolean value. */ @@ -100,7 +95,7 @@ typedef struct { void *none; literal lit; - const char *name; + uint8_t name; } data; } @@ -142,7 +137,7 @@ typedef operand_list argument_list; typedef struct { - const char *name; + uint8_t name; argument_list args; } call_expression; @@ -262,7 +257,7 @@ typedef struct expression_type type; /** NUllable. */ - const char *var; + uint8_t var; union { @@ -302,7 +297,7 @@ typedef expression_list expression; typedef struct { - const char *name; + uint8_t name; assignment_expression assign_expr; } variable_declaration; @@ -310,7 +305,7 @@ variable_declaration; static const variable_declaration empty_variable_declaration = { - .name = NULL, + .name = null_string, .assign_expr = { .oper = AO_NONE, .type = ET_NONE, .data.none = NULL } }; @@ -378,33 +373,40 @@ for_or_for_in_statement; typedef enum { STMT_NULL, - STMT_BLOCK_START, - STMT_BLOCK_END, STMT_VARIABLE, STMT_EMPTY, STMT_IF, STMT_ELSE, STMT_ELSE_IF, - STMT_DO, - + STMT_END_IF, + STMT_DO_WHILE, + STMT_END_DO_WHILE, STMT_WHILE, + + STMT_END_WHILE, STMT_FOR_OR_FOR_IN, + STMT_END_FOR_OR_FOR_IN, STMT_CONTINUE, STMT_BREAK, - STMT_RETURN, STMT_WITH, + STMT_END_WITH, STMT_LABELLED, STMT_SWITCH, + + STMT_END_SWITCH, STMT_CASE, STMT_THROW, - STMT_TRY, STMT_CATCH, + STMT_END_CATCH, STMT_FINALLY, + STMT_END_FINALLY, STMT_EXPRESSION, - STMT_SUBEXPRESSION_END, + STMT_END_SUBEXPRESSION, + STMT_FUNCTION, + STMT_END_FUNCTION, STMT_EOF } statement_type; @@ -417,9 +419,9 @@ typedef struct statement { void *none; variable_declaration_list var_stmt; - expression expr; + assignment_expression expr; for_or_for_in_statement for_stmt; - const char *name; + uint8_t name; function_declaration fun_decl; } data; diff --git a/src/libruntime/jerry-libc.c b/src/libruntime/jerry-libc.c index 765e2c926..c0b408122 100644 --- a/src/libruntime/jerry-libc.c +++ b/src/libruntime/jerry-libc.c @@ -194,7 +194,7 @@ __strtof (const char *nptr, char **endptr) (void) endptr; JERRY_UNIMPLEMENTED (); -} +} /* __strtof */ /** Calculate the length of a string. */ size_t diff --git a/src/libruntime/jerry-libc.h b/src/libruntime/jerry-libc.h index a39d8310c..d77379df0 100644 --- a/src/libruntime/jerry-libc.h +++ b/src/libruntime/jerry-libc.h @@ -44,11 +44,12 @@ extern int __isalpha (int); extern int __isdigit (int); extern int __isxdigit (int); -extern FILE* __fopen(const char *path, const char *mode); -extern int __fclose(FILE *fp); -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 int __fprintf(FILE *stream, const char *format, ...); +extern FILE* __fopen(const char *, const char *); +extern int __fclose(FILE *); +extern void __rewind(FILE *); +extern size_t __fread(void *, size_t, size_t, FILE *); +extern size_t __fwrite(const void *, size_t, size_t, FILE *); +extern int __fprintf(FILE *, const char *, ...); #define DBL_MANT_DIG ( 52) #define DBL_DIG ( 10) diff --git a/src/libruntime/pretty-printer.c b/src/libruntime/pretty-printer.c index 63ab02e84..aff907d4e 100644 --- a/src/libruntime/pretty-printer.c +++ b/src/libruntime/pretty-printer.c @@ -17,15 +17,12 @@ #include "pretty-printer.h" static int intendation; -static bool was_function_expression; -static bool was_subexpression; -static statement_type prev_stmt; +#define MAX_NAMES 100 void pp_reset (void) { - prev_stmt = STMT_EOF; intendation = 0; } @@ -39,7 +36,7 @@ pp_token (token tok) break; case TOK_STRING: - __printf ("STRING (%s)\n", tok.data.str); + __printf ("STRING (n%d)\n", tok.data.str); break; case TOK_KEYWORD: @@ -417,11 +414,11 @@ pp_formal_parameter_list (formal_parameter_list param_list) for (i = 0; i < MAX_PARAMS; i++) { - if (param_list.names[i] == NULL) + if (param_list.names[i] == null_string) break; if (i != 0) __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 "); if (func_decl.name) - __printf ("%s ", func_decl.name); + __printf ("%s ", lexer_get_string_by_id (func_decl.name)); __putchar ('('); pp_formal_parameter_list (func_decl.params); __printf (") "); - was_function_expression = true; } static void @@ -470,7 +466,7 @@ pp_operand (operand op) if (op.is_literal) pp_literal (op.data.lit); else - __printf ("%s", op.data.name); + __printf ("%s", lexer_get_string_by_id (op.data.name)); } static void @@ -515,8 +511,8 @@ pp_property_list (property_list prop_list) static void pp_call_expression (call_expression expr) { - JERRY_ASSERT (expr.name); - __printf ("%s (", expr.name); + JERRY_ASSERT (expr.name < MAX_NAMES); + __printf ("%s (", lexer_get_string_by_id (expr.name)); pp_operand_list (expr.args); __printf (")\n"); } @@ -832,18 +828,12 @@ pp_expression (expression_list expr_list) __printf (", "); pp_assignment_expression (expr_list.exprs[i]); } - - if (was_subexpression && !was_function_expression) - { - __putchar (')'); - was_subexpression = false; - } } static void 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)) { __printf (" = "); @@ -925,32 +915,9 @@ pp_for_or_for_in_statement (for_or_for_in_statement for_or_for_in_stmt) void 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) { - case STMT_BLOCK_START: - __printf ("{\n"); - intendation += 2; - break; - - case STMT_BLOCK_END: - intendation -= 2; - intend (); - __printf ("}"); + case STMT_EMPTY: break; case STMT_VARIABLE: @@ -958,44 +925,67 @@ pp_statement (statement stmt) pp_variable_declaration_list (stmt.data.var_stmt); break; - case STMT_EMPTY: - __printf (";\n"); - break; - case STMT_IF: intend (); __printf ("if ("); - pp_expression (stmt.data.expr); - __printf (") "); + pp_assignment_expression (stmt.data.expr); + __printf (") {\n"); + intendation += 2; break; case STMT_ELSE: + intendation -= 2; intend (); - __printf ("else "); + __printf ("} else {\n"); + intendation += 2; break; case STMT_ELSE_IF: + intendation -= 2; intend (); - __printf ("else if("); - pp_expression (stmt.data.expr); - __printf (") "); + __printf ("} else if("); + pp_assignment_expression (stmt.data.expr); + __printf (") {\n"); + intendation += 2; 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 (); - __printf ("do "); + __printf ("}\n"); 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: intend (); __printf ("while ("); - pp_expression (stmt.data.expr); - __printf (") "); + pp_assignment_expression (stmt.data.expr); + __printf (") {\n"); + intendation += 2; break; case STMT_FOR_OR_FOR_IN: intend (); pp_for_or_for_in_statement (stmt.data.for_stmt); + intendation += 2; break; case STMT_CONTINUE: @@ -1011,16 +1001,15 @@ pp_statement (statement stmt) case STMT_RETURN: intend (); __printf ("return "); - pp_expression (stmt.data.expr); - if (!was_function_expression) - __printf (";\n"); + pp_assignment_expression (stmt.data.expr); break; case STMT_WITH: intend (); __printf ("with ("); - pp_expression (stmt.data.expr); + pp_assignment_expression (stmt.data.expr); __printf (") "); + intendation += 2; break; case STMT_LABELLED: @@ -1031,21 +1020,22 @@ pp_statement (statement stmt) case STMT_SWITCH: intend (); __printf ("switch ("); - pp_expression (stmt.data.expr); + pp_assignment_expression (stmt.data.expr); __printf (") "); + intendation += 2; break; case STMT_CASE: intend (); __printf ("case "); - pp_expression (stmt.data.expr); + pp_assignment_expression (stmt.data.expr); __printf (":\n"); break; case STMT_THROW: intend (); __printf ("throw "); - pp_expression (stmt.data.expr); + pp_assignment_expression (stmt.data.expr); __printf (";\n"); break; @@ -1057,38 +1047,34 @@ pp_statement (statement stmt) case STMT_CATCH: intend (); __printf ("catch ("); - pp_expression (stmt.data.expr); + pp_assignment_expression (stmt.data.expr); __printf (") "); + intendation += 2; break; case STMT_FINALLY: intend (); __printf ("finally "); + intendation += 2; break; case STMT_EXPRESSION: intend (); - pp_expression (stmt.data.expr); + pp_assignment_expression (stmt.data.expr); break; - case STMT_SUBEXPRESSION_END: + case STMT_END_SUBEXPRESSION: __putchar (')'); break; case STMT_FUNCTION: intend (); pp_function_declaration (stmt.data.fun_decl); + __printf ("{\n"); + intendation += 2; break; default: JERRY_UNREACHABLE (); } - - prev_stmt = stmt.type; -} - -void pp_finish (void) -{ - if (prev_stmt == STMT_BLOCK_END) - __putchar ('\n'); } diff --git a/src/libruntime/serializer.h b/src/libruntime/serializer.h new file mode 100644 index 000000000..acb4d0f34 --- /dev/null +++ b/src/libruntime/serializer.h @@ -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 \ No newline at end of file diff --git a/src/libruntime/target/linux/jerry-libc.c b/src/libruntime/target/linux/jerry-libc.c index 2f660ccb7..699bcda72 100644 --- a/src/libruntime/target/linux/jerry-libc.c +++ b/src/libruntime/target/linux/jerry-libc.c @@ -26,6 +26,7 @@ extern void __noreturn exit(int status); extern FILE* fopen(const char *path, const char *mode); 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 fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); 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); } /* __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 * diff --git a/src/libruntime/target/linux/serializer.c b/src/libruntime/target/linux/serializer.c new file mode 100644 index 000000000..f8a32ddcf --- /dev/null +++ b/src/libruntime/target/linux/serializer.c @@ -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]); +} \ No newline at end of file diff --git a/src/libruntime/target/stm32f4/serializer.c b/src/libruntime/target/stm32f4/serializer.c new file mode 100644 index 000000000..5633a4aa0 --- /dev/null +++ b/src/libruntime/target/stm32f4/serializer.c @@ -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) \ No newline at end of file diff --git a/src/main.c b/src/main.c index 8ba6ebf05..7e8858b71 100644 --- a/src/main.c +++ b/src/main.c @@ -31,6 +31,13 @@ #include "lexer.h" #include "parser.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); @@ -85,12 +92,27 @@ fake_exit (void) #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 main (int argc, char **argv) { statement st; - bool dump_tokens = false; - bool dump_ast = false; + uint8_t dump = 0; const char *file_name = NULL; #ifdef __HOST FILE *file = NULL; @@ -102,25 +124,26 @@ main (int argc, char **argv) for (int i = 1; i < argc; i++) { if (!__strcmp ("-t", argv[i])) - dump_tokens = true; + dump |= DUMP_TOKENS; 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) file_name = argv[i]; else jerry_Exit (ERR_SEVERAL_FILES); } + check_for_several_dumps (dump); + + if (!dump) + dump |= DUMP_BYTECODE; + +#ifdef __HOST if (file_name == NULL) 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"); if (file == NULL) @@ -133,7 +156,7 @@ main (int argc, char **argv) lexer_set_source (generated_source); #endif - if (dump_ast) + if (dump & DUMP_AST) { parser_init (); 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 (); 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 (); //run_int ();