From a307f17f44b461f58441926fcbf87883f17ebe61 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 24 Feb 2019 17:53:46 +0100 Subject: Fixed CHECK_RESULT macro, use scoped allocator Scoped allocator gives us better performance and cleanup code for error cases is much cleaner --- src/buffer.c | 7 ++++-- src/parser.c | 56 +++++++++++----------------------------------- src/scoped_allocator.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/tokenizer.c | 4 ---- 4 files changed, 78 insertions(+), 49 deletions(-) create mode 100644 src/scoped_allocator.c (limited to 'src') diff --git a/src/buffer.c b/src/buffer.c index 84fb5fa..972e23a 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -16,10 +16,12 @@ void buffer_deinit(Buffer *self) { self->capacity = 0; } -static CHECK_RESULT int buffer_ensure_capacity(Buffer *self, usize new_capacity) { +static CHECK_RESULT int buffer_ensure_capacity_for(Buffer *self, usize size) { usize capacity; void *new_mem; int alloc_result; + usize new_capacity; + new_capacity = self->size + size; if(self->capacity >= new_capacity) return BUFFER_OK; @@ -43,8 +45,9 @@ static CHECK_RESULT int buffer_ensure_capacity(Buffer *self, usize new_capacity) } int buffer_append(Buffer *self, void *data, usize size) { - return_if_error(buffer_ensure_capacity(self, self->size + size)); + return_if_error(buffer_ensure_capacity_for(self, size)); am_memcpy(self->data + self->size, data, size); + self->size += size; return BUFFER_OK; } diff --git a/src/parser.c b/src/parser.c index a8fa207..875c0bc 100644 --- a/src/parser.c +++ b/src/parser.c @@ -8,6 +8,7 @@ static CHECK_RESULT int parser_parse_body(Parser *self, Ast *ast); int parser_init(Parser *self) { buffer_init(&self->ast_objects); + return_if_error(scoped_allocator_init(&self->allocator)); return PARSER_OK; } @@ -17,6 +18,7 @@ void parser_deinit(Parser *self) { ast_deinit((Ast*)&self->ast_objects.data[i]); } buffer_deinit(&self->ast_objects); + scoped_allocator_deinit(&self->allocator); } /* @@ -38,7 +40,7 @@ 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(am_malloc(sizeof(LhsExpr), (void**)result)); + return_if_error(scoped_allocator_alloc(&self->allocator, sizeof(LhsExpr), (void**)result)); lhsexpr_init(*result, isConst, var_name); return PARSER_OK; } @@ -59,7 +61,7 @@ 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(am_malloc(sizeof(FunctionDecl), (void**)func_decl)); + return_if_error(scoped_allocator_alloc(&self->allocator, sizeof(FunctionDecl), (void**)func_decl)); funcdecl_init(*func_decl); for(;;) { @@ -74,11 +76,7 @@ static CHECK_RESULT int parser_parse_function_decl(Parser *self, FunctionDecl ** return PARSER_OK; cleanup: - if(*func_decl) { - funcdecl_deinit(*func_decl); - am_free(*func_decl); - *func_decl = NULL; - } + *func_decl = NULL; return PARSER_ERR; } @@ -99,7 +97,7 @@ 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(am_malloc(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; } @@ -114,14 +112,14 @@ static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) { func_decl = NULL; func_call = NULL; - cleanup_if_error(parser_parse_function_decl(self, &func_decl)); + return_if_error(parser_parse_function_decl(self, &func_decl)); if(func_decl) { rhs_expr->type = AST_FUNCTION_DECL; rhs_expr->value.func_decl = func_decl; return PARSER_OK; } - cleanup_if_error(parser_parse_function_call(self, &func_call)); + return_if_error(parser_parse_function_call(self, &func_call)); if(func_call) { rhs_expr->type = AST_FUNCTION_CALL; rhs_expr->value.func_call = func_call; @@ -132,17 +130,6 @@ static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) { /* TODO: Convert token to string */ tokenizer_print_error(&self->tokenizer, "Expected function declaration or function call, got token: %d"); return PARSER_UNEXPECTED_TOKEN; - - cleanup: - if(func_decl) { - funcdecl_deinit(func_decl); - am_free(func_decl); - } - if(func_call) { - /*funccall_deinit(func_call);*/ - am_free(func_call); - } - return PARSER_ERR; } /* @@ -157,7 +144,7 @@ int parser_parse_body(Parser *self, Ast *ast) { if(lhs_expr) return_if_error(tokenizer_accept(&self->tokenizer, TOK_EQUALS)); - cleanup_if_error(parser_parse_rhs(self, &rhs_expr)); + return_if_error(parser_parse_rhs(self, &rhs_expr)); if(lhs_expr) { lhs_expr->rhs_expr = rhs_expr; ast->type = AST_LHS; @@ -166,13 +153,6 @@ int parser_parse_body(Parser *self, Ast *ast) { *ast = rhs_expr; } return PARSER_OK; - - cleanup: - if(lhs_expr) { - lhsexpr_deinit(lhs_expr); - am_free(lhs_expr); - } - return PARSER_ERR; } /* @@ -180,27 +160,17 @@ ROOT = BODY* */ int parser_parse_buffer(Parser *self, BufferView code_buffer) { Ast ast; - ast = ast_none(); return_if_error(tokenizer_init(&self->tokenizer, code_buffer)); for(;;) { bool isEof; - cleanup_if_error(tokenizer_consume_if(&self->tokenizer, TOK_END_OF_FILE, &isEof)); + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_END_OF_FILE, &isEof)); if(isEof) - goto cleanup_noerr; + break; - cleanup_if_error(parser_parse_body(self, &ast)); - cleanup_if_error(buffer_append(&self->ast_objects, &ast, sizeof(ast))); - /* For cleanup, we only want to cleanup the last created ast after parser_parse_body */ - ast = ast_none(); + return_if_error(parser_parse_body(self, &ast)); + return_if_error(buffer_append(&self->ast_objects, &ast, sizeof(ast))); } - cleanup_noerr: - tokenizer_deinit(&self->tokenizer); return PARSER_OK; - - cleanup: - tokenizer_deinit(&self->tokenizer); - ast_deinit(&ast); - return PARSER_ERR; } diff --git a/src/scoped_allocator.c b/src/scoped_allocator.c new file mode 100644 index 0000000..ea99774 --- /dev/null +++ b/src/scoped_allocator.c @@ -0,0 +1,60 @@ +#include "../include/scoped_allocator.h" +#include "../include/alloc.h" +#include + +#define ALLOC_NODE_SIZE 4096 + +int scoped_allocator_node_init(ScopedAllocatorNode *self) { + self->data = NULL; + self->size = 0; + self->next = NULL; + return am_malloc(ALLOC_NODE_SIZE, (void**)&self->data); +} + +void scoped_allocator_node_deinit(ScopedAllocatorNode *self) { + am_free(self->data); + self->data = NULL; + self->size = 0; + if(self->next) { + scoped_allocator_node_deinit(self->next); + am_free(self->next); + self->next = NULL; + } +} + +int scoped_allocator_init(ScopedAllocator *self) { + return_if_error(scoped_allocator_node_init(&self->head)); + self->current = &self->head; + return 0; +} +void scoped_allocator_deinit(ScopedAllocator *self) { + scoped_allocator_node_deinit(&self->head); + self->current = NULL; +} + +static CHECK_RESULT int scoped_allocator_ensure_capacity_for(ScopedAllocator *self, usize size) { + void *new_node; + new_node = NULL; + + if(self->current->size + size > ALLOC_NODE_SIZE) { + return_if_error(am_malloc(sizeof(ScopedAllocatorNode), &new_node)); + cleanup_if_error(scoped_allocator_node_init(new_node)); + self->current->next = new_node; + self->current = new_node; + } + return 0; + + cleanup: + if(new_node) + am_free(new_node); + return -1; +} + +int scoped_allocator_alloc(ScopedAllocator *self, usize size, void **mem) { + assert(self->current); + assert(size <= ALLOC_NODE_SIZE); + return_if_error(scoped_allocator_ensure_capacity_for(self, size)); + *mem = &self->current->data[self->current->size]; + self->current->size += size; + return 0; +} \ No newline at end of file diff --git a/src/tokenizer.c b/src/tokenizer.c index f1763a5..fda3e40 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -26,10 +26,6 @@ int tokenizer_init(Tokenizer *self, BufferView code) { return 0; } -void tokenizer_deinit(Tokenizer *self) { - (void)self; -} - static int tokenizer_get_char(Tokenizer *self) { assert(self->index >= 0 && self->index < (int)self->code.size); return self->code.data[self->index]; -- cgit v1.2.3