aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/misc.h2
-rw-r--r--include/parser.h4
-rw-r--r--include/scoped_allocator.h27
-rw-r--r--include/tokenizer.h1
-rw-r--r--src/buffer.c7
-rw-r--r--src/parser.c56
-rw-r--r--src/scoped_allocator.c60
-rw-r--r--src/tokenizer.c4
8 files changed, 109 insertions, 52 deletions
diff --git a/include/misc.h b/include/misc.h
index 633ccfd..9cb2dde 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -12,7 +12,7 @@ do { \
#define cleanup_if_error(result) do { if((result) != 0) goto cleanup; } while(0)
#if defined(__GNUC__) && __GNUC__ >= 4
-#define CHECK_RESULT __attribute__ ((CHECK_RESULT))
+#define CHECK_RESULT __attribute__ ((warn_unused_result))
#elif defined(_MSC_VER) && _MSC_VER >= 1700
#define CHECK_RESULT _Check_return_
#else
diff --git a/include/parser.h b/include/parser.h
index d66a096..e90871f 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -4,6 +4,7 @@
#include "buffer.h"
#include "buffer_view.h"
#include "tokenizer.h"
+#include "scoped_allocator.h"
#define PARSER_OK 0
/* General error */
@@ -11,8 +12,9 @@
#define PARSER_UNEXPECTED_TOKEN -2
typedef struct {
- Buffer ast_objects;
Tokenizer tokenizer;
+ ScopedAllocator allocator;
+ Buffer ast_objects;
} Parser;
CHECK_RESULT int parser_init(Parser *self);
diff --git a/include/scoped_allocator.h b/include/scoped_allocator.h
new file mode 100644
index 0000000..1193439
--- /dev/null
+++ b/include/scoped_allocator.h
@@ -0,0 +1,27 @@
+#ifndef AMALGAM_SCOPED_ALLOCATOR_H
+#define AMALGAM_SCOPED_ALLOCATOR_H
+
+#include "misc.h"
+#include "types.h"
+
+typedef struct ScopedAllocatorNode ScopedAllocatorNode;
+
+struct ScopedAllocatorNode {
+ char *data;
+ usize size;
+ ScopedAllocatorNode *next;
+};
+
+typedef struct {
+ ScopedAllocatorNode head;
+ ScopedAllocatorNode *current;
+} ScopedAllocator;
+
+CHECK_RESULT int scoped_allocator_node_init(ScopedAllocatorNode *self);
+void scoped_allocator_node_deinit(ScopedAllocatorNode *self);
+
+CHECK_RESULT int scoped_allocator_init(ScopedAllocator *self);
+void scoped_allocator_deinit(ScopedAllocator *self);
+CHECK_RESULT int scoped_allocator_alloc(ScopedAllocator *self, usize size, void **mem);
+
+#endif \ No newline at end of file
diff --git a/include/tokenizer.h b/include/tokenizer.h
index f572860..9584542 100644
--- a/include/tokenizer.h
+++ b/include/tokenizer.h
@@ -32,7 +32,6 @@ typedef struct {
} Tokenizer;
CHECK_RESULT int tokenizer_init(Tokenizer *self, BufferView code);
-void tokenizer_deinit(Tokenizer *self);
CHECK_RESULT int tokenizer_next(Tokenizer *self, Token *token);
CHECK_RESULT int tokenizer_accept(Tokenizer *self, Token expected_token);
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 <assert.h>
+
+#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];