From 76d85a10f6cda93eba29dad5372e8160af7289c8 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 27 Feb 2019 22:26:35 +0100 Subject: Use multiple threads to parse --- src/parser.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 107 insertions(+), 27 deletions(-) (limited to 'src/parser.c') diff --git a/src/parser.c b/src/parser.c index 78b0018..da85292 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,19 +1,51 @@ #include "../include/parser.h" #include "../include/ast.h" -#include "../include/misc.h" -#include "../include/alloc.h" +#include "../include/compiler.h" +#include "../include/std/misc.h" +#include "../include/std/file.h" +#include "../include/std/mem.h" +#include "../include/std/log.h" #include +#include +#include +static CHECK_RESULT int parser_queue_file(Parser *self, BufferView path); static CHECK_RESULT int parser_parse_body(Parser *self, Ast *ast); -int parser_init(Parser *self) { - return_if_error(scoped_allocator_init(&self->allocator)); - return_if_error(buffer_init(&self->ast_objects, &self->allocator)); - return PARSER_OK; +int parser_thread_data_init(ParserThreadData *self) { + am_memset(&self->allocator, 0, sizeof(self->allocator)); + am_memset(&self->thread, 0, sizeof(self->thread)); + self->status = PARSER_THREAD_STATUS_NEW; + return scoped_allocator_init(&self->allocator); } -void parser_deinit(Parser *self) { +int parser_thread_data_deinit(ParserThreadData *self) { scoped_allocator_deinit(&self->allocator); + return amal_thread_deinit(&self->thread); +} + +int parser_thread_data_start(ParserThreadData *self, AmalThreadCallbackFunc callback_func, void *userdata) { + return_if_error(amal_thread_deinit(&self->thread)); + return_if_error(amal_thread_create(&self->thread, AMAL_THREAD_JOINABLE, "Parser", callback_func, userdata)); + self->status = PARSER_THREAD_STATUS_RUNNING; + return 0; +} + +int parser_thread_data_join(ParserThreadData *self, void **result) { + int retval; + if(self->status == PARSER_THREAD_STATUS_NEW) + return 0; + retval = amal_thread_join(&self->thread, result); + if(retval == 0 || retval == AMAL_THREAD_NOT_JOINABLE) + self->status = PARSER_THREAD_STATUS_IDLE; + return retval; +} + +int parser_init(Parser *self, amal_compiler *compiler, ScopedAllocator *allocator) { + self->allocator = allocator; + self->compiler = compiler; + self->started = bool_false; + return buffer_init(&self->ast_objects, self->allocator); } /* @@ -34,8 +66,8 @@ static CHECK_RESULT int parser_parse_lhs(Parser *self, LhsExpr **result) { return_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER)); var_name = self->tokenizer.value.identifier; - fprintf(stderr, "var name: %.*s\n", (int)var_name.size, var_name.data); - return_if_error(scoped_allocator_alloc(&self->allocator, sizeof(LhsExpr), (void**)result)); + amal_log_debug("var name: %.*s", (int)var_name.size, var_name.data); + return_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)result)); lhsexpr_init(*result, isConst, var_name); return PARSER_OK; } @@ -56,23 +88,19 @@ static CHECK_RESULT int parser_parse_function_decl(Parser *self, FunctionDecl ** /* TODO: Parse return types */ return_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_BRACE)); - return_if_error(scoped_allocator_alloc(&self->allocator, sizeof(FunctionDecl), (void**)func_decl)); - cleanup_if_error(funcdecl_init(*func_decl, &self->allocator)); + return_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionDecl), (void**)func_decl)); + return_if_error(funcdecl_init(*func_decl, self->allocator)); for(;;) { Ast body_obj; - cleanup_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_BRACE, &result)); + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_BRACE, &result)); if(result) break; - cleanup_if_error(parser_parse_body(self, &body_obj)); - cleanup_if_error(funcdecl_add_to_body(*func_decl, body_obj)); + return_if_error(parser_parse_body(self, &body_obj)); + return_if_error(funcdecl_add_to_body(*func_decl, body_obj)); } return PARSER_OK; - - cleanup: - *func_decl = NULL; - return PARSER_ERR; } /* @@ -92,20 +120,33 @@ static CHECK_RESULT int parser_parse_function_call(Parser *self, FunctionCall ** /* TODO: Parse arguments */ return_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN)); - return_if_error(scoped_allocator_alloc(&self->allocator, sizeof(FunctionCall), (void**)func_call)); + return_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionCall), (void**)func_call)); funccall_init(*func_call, func_name); return PARSER_OK; } /* -RHS = FUNC_DECL | FUNC_CALL +IMPORT = IMPORT_SYMBOL +*/ +static CHECK_RESULT int parser_parse_import(Parser *self, Import **import) { + bool result; + + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IMPORT, &result)); + if(!result) + return PARSER_OK; + + return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Import), (void**)import)); + import_init(*import, self->tokenizer.value.string); + return PARSER_OK; +} + +/* +RHS = FUNC_DECL | FUNC_CALL | IMPORT */ static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) { FunctionDecl *func_decl; FunctionCall *func_call; - Token token; - func_decl = NULL; - func_call = NULL; + Import *import; return_if_error(parser_parse_function_decl(self, &func_decl)); if(func_decl) { @@ -121,9 +162,16 @@ static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) { return PARSER_OK; } - return_if_error(tokenizer_next(&self->tokenizer, &token)); + return_if_error(parser_parse_import(self, &import)); + if(import) { + rhs_expr->type = AST_IMPORT; + rhs_expr->value.import = import; + return_if_error(parser_queue_file(self, import->path)); + return PARSER_OK; + } + /* TODO: Convert token to string */ - tokenizer_print_error(&self->tokenizer, "Expected function declaration or function call, got token: %d"); + tokenizer_print_error(&self->tokenizer, "Expected function declaration or function call"); return PARSER_UNEXPECTED_TOKEN; } @@ -153,9 +201,9 @@ int parser_parse_body(Parser *self, Ast *ast) { /* ROOT = BODY* */ -int parser_parse_buffer(Parser *self, BufferView code_buffer) { +int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_name) { Ast ast; - return_if_error(tokenizer_init(&self->tokenizer, code_buffer)); + return_if_error(tokenizer_init(&self->tokenizer, code_buffer, buffer_name)); for(;;) { bool isEof; @@ -169,3 +217,35 @@ int parser_parse_buffer(Parser *self, BufferView code_buffer) { return PARSER_OK; } + +int parser_parse_file(Parser *self, BufferView filepath) { + int result; + int mapped_file_deinit_result; + MappedFile mapped_file; + char *filepath_tmp; + + amal_log_debug("Parsing %.*s", (int)filepath.size, filepath.data); + assert(!self->started && "Parser can't be reused. Create a new parser."); + self->started = bool_true; + /* TODO: Somehow free this... */ + /*return_if_error(scoped_allocator_alloc(self->allocator, filepath.size + 1, (void**)&filepath_tmp));*/ + filepath_tmp = malloc(filepath.size + 1); + am_memcpy(filepath_tmp, filepath.data, filepath.size); + filepath_tmp[filepath.size] = '\0'; + result = mapped_file_init(&mapped_file, filepath_tmp, MAPPED_FILE_READ); + if(result != 0) return result; + result = parser_parse_buffer(self, create_buffer_view(mapped_file.file_data, mapped_file.file_size), filepath); + mapped_file_deinit_result = mapped_file_deinit(&mapped_file); + return result != 0 ? result : mapped_file_deinit_result; +} + +/* +Path can be path to included library path (or system library path) in which case +the path separator is a dot, otherwise the path separator is forward slash '/' +*/ +int parser_queue_file(Parser *self, BufferView path) { + /* TODO: Do not load same path twice or the compile will fail (and it can have recursive import) also for performance reasons */ + /* TODO: Parse special path (to include library path with dots) */ + return_if_error(amal_compiler_load_file(self->compiler, path)); + return PARSER_OK; +} \ No newline at end of file -- cgit v1.2.3