aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast.c229
-rw-r--r--src/compiler.c12
-rw-r--r--src/parser.c312
-rw-r--r--src/ssa/ssa.c40
4 files changed, 321 insertions, 272 deletions
diff --git a/src/ast.c b/src/ast.c
index d0a5030..7d25401 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -4,37 +4,38 @@
#include "../include/std/hash.h"
#include <assert.h>
-#define throw(result) do { longjmp(context->env, (result)); } while(0)
+#define throw(result) do { throw_debug_msg; longjmp(context->env, (result)); } while(0)
#define throw_if_error(result) \
-do { \
- int return_if_result; \
- return_if_result = (result); \
- if((return_if_result) != 0) \
- throw(return_if_result); \
-} while(0)
+ do { \
+ int return_if_result; \
+ return_if_result = (result); \
+ if((return_if_result) != 0) \
+ throw(return_if_result); \
+ } while(0)
static void ast_resolve(Ast *self, AstCompilerContext *context);
-Ast ast_none() {
- Ast ast;
- ast.value.func_decl = NULL;
- ast.type = AST_NONE;
- ast.resolve_status = AST_NOT_RESOLVED;
- ast.resolved_type = NULL;
- return ast;
+static void resolve_data_init(AstResolveData *self) {
+ self->status = AST_NOT_RESOLVED;
+ self->type = NULL;
}
-void ast_init(Ast *self, void *value, AstType type) {
- self->value.data = value;
- self->type = type;
- self->resolve_status = AST_NOT_RESOLVED;
- self->resolved_type = NULL;
+int ast_create(ScopedAllocator *allocator, void *value, AstType type, Ast **result) {
+ return_if_error(scoped_allocator_alloc(allocator, sizeof(Ast), (void**)result));
+ (*result)->value.data = value;
+ (*result)->type = type;
+ resolve_data_init(&(*result)->resolve_data);
+ return 0;
+}
+
+static bool ast_is_decl(Ast *self) {
+ /* TODO: Add more types as they are introduced */
+ return self->type == AST_FUNCTION_DECL || self->type == AST_STRUCT_DECL;
}
BufferView ast_get_name(Ast *self) {
BufferView name;
switch(self->type) {
- case AST_NONE:
case AST_FUNCTION_DECL:
case AST_STRUCT_DECL:
case AST_IMPORT:
@@ -87,7 +88,7 @@ int lhsexpr_init(LhsExpr *self, bool is_pub, bool is_const, BufferView var_name,
self->is_const = is_const;
variable_init(&self->type, create_buffer_view_null());
self->var_name = var_name;
- self->rhs_expr = ast_none();
+ self->rhs_expr = NULL;
if(is_pub && allocator)
return_if_error(scoped_allocator_create_mutex(allocator, &self->mutex));
else
@@ -116,15 +117,15 @@ void variable_init(Variable *self, BufferView name) {
}
void binop_init(Binop *self) {
- self->lhs = ast_none();
- self->rhs = ast_none();
+ self->lhs = NULL;
+ self->rhs = NULL;
self->type = BINOP_ADD;
self->grouped = bool_false;
}
int scope_init(Scope *self, Scope *parent, ScopedAllocator *allocator) {
return_if_error(buffer_init(&self->ast_objects, allocator));
- return_if_error(hash_map_init(&self->named_objects, allocator, sizeof(Ast), hash_compare_string, amal_hash_string));
+ return_if_error(hash_map_init(&self->named_objects, allocator, sizeof(Ast*), hash_compare_string, amal_hash_string));
self->parent = parent;
return 0;
}
@@ -143,7 +144,7 @@ int file_scope_reference_init(FileScopeReference *self, BufferView canonical_pat
}
int scope_add_child(Scope *self, Ast *child) {
- Ast existing_child;
+ Ast *existing_child;
bool child_already_exists;
/* TODO: Implement for parameter */
@@ -154,9 +155,9 @@ int scope_add_child(Scope *self, Ast *child) {
if(child_already_exists)
return AST_ERR_DEF_DUP;
- cleanup_if_error(hash_map_insert(&self->named_objects, var_name, child));
+ cleanup_if_error(hash_map_insert(&self->named_objects, var_name, &child));
}
- cleanup_if_error(buffer_append(&self->ast_objects, child, sizeof(Ast)));
+ cleanup_if_error(buffer_append(&self->ast_objects, &child, sizeof(Ast*)));
return 0;
cleanup:
@@ -164,20 +165,20 @@ int scope_add_child(Scope *self, Ast *child) {
}
void scope_resolve(Scope *self, AstCompilerContext *context) {
- Ast *ast;
- Ast *ast_end;
+ Ast **ast;
+ Ast **ast_end;
ast = buffer_start(&self->ast_objects);
ast_end = buffer_end(&self->ast_objects);
context->scope = self;
for(; ast != ast_end; ++ast) {
- ast_resolve(ast, context);
+ ast_resolve(*ast, context);
}
context->scope = self->parent;
}
static LhsExpr* scope_get_resolved_variable(Scope *self, AstCompilerContext *context, BufferView name) {
- Ast result;
+ Ast *result;
bool exists;
Scope *prev_scope;
@@ -200,54 +201,82 @@ static LhsExpr* scope_get_resolved_variable(Scope *self, AstCompilerContext *con
*/
prev_scope = context->scope;
context->scope = self;
- ast_resolve(&result, context);
+ ast_resolve(result, context);
context->scope = prev_scope;
- assert(result.type == AST_LHS);
- return result.value.lhs_expr;
+ assert(result->type == AST_LHS);
+ return result->value.lhs_expr;
}
-/* @resolved_type is the same field as the ast resolved_type for the variable @self */
-static void variable_resolve(Variable *self, AstCompilerContext *context, LhsExpr **resolved_type) {
- /* TODO: Verify this is correct in all cases */
- *resolved_type = scope_get_resolved_variable(context->scope, context, self->name);
+static void variable_resolve(Variable *self, AstCompilerContext *context, AstResolveData *resolve_data) {
+ if(!resolve_data->type)
+ resolve_data->type = scope_get_resolved_variable(context->scope, context, self->name);
}
-static void lhsexpr_resolve(Ast *self, AstCompilerContext *context) {
- LhsExpr *lhs_expr;
- lhs_expr = self->value.lhs_expr;
+static LhsExpr* lhsexpr_resolve_rhs(Ast *ast, AstCompilerContext *context, LhsExpr *lhs_expr) {
+ LhsExpr *rhs_resolved_type;
+ ast_resolve(ast, context);
+ if(ast_is_decl(ast))
+ rhs_resolved_type = lhs_expr;
+ else
+ rhs_resolved_type = ast->resolve_data.type;
+ return rhs_resolved_type;
+}
- if(lhs_expr->type.name.data)
- variable_resolve(&lhs_expr->type, context, &self->resolved_type);
- self->resolve_status = AST_RESOLVED;
- ast_resolve(&lhs_expr->rhs_expr, context);
+static void lhsexpr_resolve(Ast *ast, AstCompilerContext *context) {
+ LhsExpr *self;
+ LhsExpr *rhs_resolve_type;
- if(self->resolved_type &&
- lhs_expr->rhs_expr.type != AST_NONE &&
- self->resolved_type != lhs_expr->rhs_expr.resolved_type) {
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data),
- "Variable type and variable assignment type (right-hand side) do not match");
- throw(AST_ERR);
+ assert(ast->type == AST_LHS);
+ self = ast->value.lhs_expr;
+ rhs_resolve_type = NULL;
+
+ if(self->type.name.data)
+ variable_resolve(&self->type, context, &ast->resolve_data);
+
+ /*
+ TODO: When parameters and return types are implemented, AST_RESOLVE_END should be set after
+ the parameters and return types have been resolved as recursive function calls should
+ be allowed but recursive function calls still require parameters and return types to be known.
+ */
+ if(self->rhs_expr) {
+ if(self->rhs_expr->type == AST_FUNCTION_DECL)
+ ast->resolve_data.status = AST_RESOLVED;
+
+ rhs_resolve_type = lhsexpr_resolve_rhs(self->rhs_expr, context, self);
+
+ /* self->rhs_expr can be null here because this is valid: var num: i32; */
+ if(ast->resolve_data.type &&
+ self->rhs_expr &&
+ ast->resolve_data.type != rhs_resolve_type) {
+ tokenizer_print_error(&context->parser->tokenizer,
+ tokenizer_get_code_reference_index(&context->parser->tokenizer, self->type.name.data),
+ "Variable type and variable assignment type (right-hand side) do not match");
+ throw(AST_ERR);
+ }
}
- self->resolved_type = lhs_expr->rhs_expr.resolved_type;
+
+ if(rhs_resolve_type)
+ ast->resolve_data.type = rhs_resolve_type;
}
/* LhsExpr has to be resolved before this is called */
+#if 0
static Scope* lhsexpr_get_scope(LhsExpr *self) {
- switch(self->rhs_expr.type) {
+ switch(self->rhs_expr->type) {
case AST_FUNCTION_DECL:
- return &self->rhs_expr.value.func_decl->body;
+ return &self->rhs_expr->value.func_decl->body;
case AST_STRUCT_DECL:
- return &self->rhs_expr.value.struct_decl->body;
+ return &self->rhs_expr->value.struct_decl->body;
case AST_IMPORT:
- return self->rhs_expr.value.import->file_scope->scope;
+ return self->rhs_expr->value.import->file_scope->scope;
default:
break;
}
assert(bool_false && "Expected lhsexpr_get_scope to only be called for function decl and struct decl");
return NULL;
}
+#endif
static void import_resolve(Ast *self, AstCompilerContext *context) {
Import *import;
@@ -258,32 +287,27 @@ static void import_resolve(Ast *self, AstCompilerContext *context) {
/* TODO: Convert all scopes to structs and set import->resolved_type to import->file_scope->scope; */
}
-static void funcdecl_resolve(Ast *self, AstCompilerContext *context) {
- /* TODO: Implement */
- FunctionDecl *func_decl;
- assert(self->type == AST_FUNCTION_DECL);
- func_decl = self->value.func_decl;
- self->resolve_status = AST_RESOLVED;
- scope_resolve(&func_decl->body, context);
+static void funcdecl_resolve(FunctionDecl *self, AstCompilerContext *context) {
+ /* TODO: Implement parameters and return types */
+ scope_resolve(&self->body, context);
}
static void funccall_resolve(Ast *self, AstCompilerContext *context) {
FunctionCall *func_call;
- Ast *ast;
- Ast *ast_end;
+ Ast **ast;
+ Ast **ast_end;
func_call = self->value.func_call;
- variable_resolve(&func_call->func, context, &self->resolved_type);
+ variable_resolve(&func_call->func, context, &self->resolve_data);
ast = buffer_start(&func_call->args);
ast_end = buffer_end(&func_call->args);
for(; ast != ast_end; ++ast) {
- ast_resolve(ast, context);
+ ast_resolve(*ast, context);
}
}
static void structdecl_resolve(Ast *self, AstCompilerContext *context) {
- /* TODO: What to do with resolved_type? */
StructDecl *struct_decl;
struct_decl = self->value.struct_decl;
scope_resolve(&struct_decl->body, context);
@@ -293,26 +317,52 @@ static void structfield_resolve(Ast *self, AstCompilerContext *context) {
/* TODO: Implement */
StructField *struct_field;
struct_field = self->value.struct_field;
- variable_resolve(&struct_field->type, context, &self->resolved_type);
+ variable_resolve(&struct_field->type, context, &self->resolve_data);
}
-static void binop_resolve(Binop *self, AstCompilerContext *context) {
- /* TODO: Implement */
- ast_resolve(&self->lhs, context);
- if(self->rhs.type == AST_VARIABLE) {
- Scope *prev_scope;
- assert(self->lhs.resolved_type);
- prev_scope = context->scope;
- context->scope = lhsexpr_get_scope(self->lhs.resolved_type);
- assert(context->scope);
- ast_resolve(&self->rhs, context);
- context->scope = prev_scope;
+static void binop_resolve(Ast *ast, AstCompilerContext *context) {
+ Binop *self;
+ assert(ast->type == AST_BINOP);
+ self = ast->value.binop;
+ ast_resolve(self->lhs, context);
+ #if 0 /* TODO: Readd this once mutex has been added for types */
+ if(self->type == BINOP_DOT && self->rhs->type == AST_VARIABLE) {
+ Scope *lhs_scope;
+ lhs_scope = lhsexpr_get_scope(self->lhs->resolve_data.type);
+ self->rhs->resolve_data.type = scope_get_resolved_variable(lhs_scope, context, self->rhs->value.variable->name);
+ self->rhs->resolve_data.status = AST_RESOLVED;
+ ast->resolve_data.type = self->rhs->resolve_data.type;
} else {
- ast_resolve(&self->rhs, context);
+ ast_resolve(self->rhs, context);
+ /* TODO: Convert types that can be safely converted */
+ if(self->lhs->resolve_data.type != self->rhs->resolve_data.type) {
+ /*
+ TODO: For this first error, only print the line without a reference to code.
+ This requires change in tokenizer_print_error to be able to take a line as reference.
+ */
+ tokenizer_print_error(&context->parser->tokenizer,
+ tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self->lhs).data),
+ "Right-hand side and left-hand side are different types");
+ tokenizer_print_error(&context->parser->tokenizer,
+ tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self->lhs).data),
+ "Left-hand side is of type %.*s",
+ self->rhs->resolve_data.type->var_name.size,
+ self->lhs->resolve_data.type->var_name.data);
+ tokenizer_print_error(&context->parser->tokenizer,
+ tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self->rhs).data),
+ "Right-hand side is of type %.*s",
+ self->rhs->resolve_data.type->var_name.size,
+ self->rhs->resolve_data.type->var_name.data);
+ throw(AST_ERR);
+ }
}
+ #else
+ ast_resolve(self->rhs, context);
+ #endif
}
void ast_resolve(Ast *self, AstCompilerContext *context) {
+ assert(self);
/*
TODO: Move these to the types that need checks for recursive dependency (function declaration, struct declaration)
For function declaration, it should be marked as resolved when the signature has been resolved
@@ -320,23 +370,22 @@ void ast_resolve(Ast *self, AstCompilerContext *context) {
because the body can have function call that calls functions that are resolving
or even recursive function call, which should be allowed.
*/
- if(self->resolve_status == AST_RESOLVED) {
+ if(self->resolve_data.status == AST_RESOLVED) {
return;
- } else if(self->resolve_status == AST_RESOLVING) {
+ } else if(self->resolve_data.status == AST_RESOLVING) {
tokenizer_print_error(&context->parser->tokenizer,
tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data),
"Found recursive dependency");
throw(AST_ERR);
}
- self->resolve_status = AST_RESOLVING;
+ self->resolve_data.status = AST_RESOLVING;
switch(self->type) {
- case AST_NONE:
case AST_NUMBER:
/* Nothing to resolve for numbers */
break;
case AST_FUNCTION_DECL:
- funcdecl_resolve(self, context);
+ funcdecl_resolve(self->value.func_decl, context);
break;
case AST_FUNCTION_CALL:
funccall_resolve(self, context);
@@ -358,12 +407,12 @@ void ast_resolve(Ast *self, AstCompilerContext *context) {
/* TODO: Convert special combinations. For example \n to newline */
break;
case AST_VARIABLE:
- variable_resolve(self->value.variable, context, &self->resolved_type);
+ variable_resolve(self->value.variable, context, &self->resolve_data);
break;
case AST_BINOP:
- binop_resolve(self->value.binop, context);
+ binop_resolve(self, context);
break;
}
/* TODO: See comment at the top of this function */
- self->resolve_status = AST_RESOLVED;
+ self->resolve_data.status = AST_RESOLVED;
}
diff --git a/src/compiler.c b/src/compiler.c
index 50678d8..cc35d1e 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -41,7 +41,7 @@ static usize strnlen(const char *str, usize max_length) {
static CHECK_RESULT int create_default_type(amal_compiler *compiler, const char *name) {
StructDecl *struct_decl;
LhsExpr *lhs_expr;
- Ast expr;
+ Ast *expr;
return_if_error(scoped_allocator_alloc(&compiler->allocator, sizeof(StructDecl), (void**)&struct_decl));
return_if_error(structdecl_init(struct_decl, &compiler->root_scope, &compiler->allocator));
@@ -50,11 +50,11 @@ static CHECK_RESULT int create_default_type(amal_compiler *compiler, const char
return_if_error(lhsexpr_init(lhs_expr, bool_true, bool_true,
create_buffer_view(name, strnlen(name, PATH_MAX)),
NULL));
- ast_init(&lhs_expr->rhs_expr, struct_decl, AST_STRUCT_DECL);
- ast_init(&expr, lhs_expr, AST_LHS);
- expr.resolved_type = lhs_expr;
- expr.resolve_status = AST_RESOLVED;
- return scope_add_child(&compiler->root_scope, &expr);
+ return_if_error(ast_create(&compiler->allocator, struct_decl, AST_STRUCT_DECL, &lhs_expr->rhs_expr));
+ return_if_error(ast_create(&compiler->allocator, lhs_expr, AST_LHS, &expr));
+ expr->resolve_data.type = lhs_expr;
+ expr->resolve_data.status = AST_RESOLVED;
+ return scope_add_child(&compiler->root_scope, expr);
}
static CHECK_RESULT int init_default_types(amal_compiler *compiler) {
diff --git a/src/parser.c b/src/parser.c
index b1764a1..9e92ddd 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -11,19 +11,6 @@
#include <stdlib.h>
#include <assert.h>
-#ifdef AMAL_PEDANTIC
- #define throw_debug_msg do {} while(0)
-#else
- #define throw_debug_msg do { amal_log_info("Throwing from %s:%d", __FUNCTION__, __LINE__); } while(0)
-#endif
-
-#define THROWABLE CHECK_RESULT int
-#define try(result) \
-do { \
- int return_if_result; \
- return_if_result = (result); \
- (void)return_if_result; \
-} while(0)
#define throw(result) do { throw_debug_msg; longjmp(self->parse_env, (result)); } while(0)
#define throw_if_error(result) \
do { \
@@ -33,10 +20,10 @@ do { \
throw(return_if_result); \
} while(0)
-static THROWABLE parser_parse_rhs_start(Parser *self, Ast *rhs_expr, bool is_standalone);
-static THROWABLE parser_parse_body(Parser *self, Ast *ast);
-static THROWABLE parser_parse_struct_body(Parser *self, Ast *ast);
-static THROWABLE parser_queue_file(Parser *self, BufferView path, FileScopeReference **file_scope);
+static CHECK_RESULT Ast* parser_parse_rhs_start(Parser *self, bool is_standalone);
+static CHECK_RESULT Ast* parser_parse_body(Parser *self);
+static CHECK_RESULT Ast* parser_parse_struct_body(Parser *self);
+static void parser_queue_file(Parser *self, BufferView path, FileScopeReference **file_scope);
int parser_thread_data_init(ParserThreadData *self) {
am_memset(&self->allocator, 0, sizeof(self->allocator));
@@ -82,23 +69,23 @@ static bool parser_is_global_scope(Parser *self) {
/*
BODY_LOOP = BODY* @end_token
*/
-static THROWABLE parser_parse_body_loop(Parser *self, Scope *scope, Token end_token) {
+static void parser_parse_body_loop(Parser *self, Scope *scope, Token end_token) {
int result;
for(;;) {
- Ast body_obj;
+ Ast *body_obj;
bool is_end_token;
throw_if_error(tokenizer_consume_if(&self->tokenizer, end_token, &is_end_token));
if(is_end_token)
break;
- try(parser_parse_body(self, &body_obj));
- result = scope_add_child(scope, &body_obj);
+ body_obj = parser_parse_body(self);
+ result = scope_add_child(scope, body_obj);
if(result == 0) {
continue;
} else if(result == AST_ERR_DEF_DUP) {
/* TODO: Convert ast type to string for error message */
BufferView obj_name;
- obj_name = ast_get_name(&body_obj);
+ obj_name = ast_get_name(body_obj);
self->error = tokenizer_create_error(&self->tokenizer,
tokenizer_get_code_reference_index(&self->tokenizer, obj_name.data),
"Variable with the name %.*s was declared twice in the same scope", obj_name.size, obj_name.data);
@@ -108,30 +95,29 @@ static THROWABLE parser_parse_body_loop(Parser *self, Scope *scope, Token end_to
throw(result);
}
}
- return PARSER_OK;
}
/*
STRUCT_BODY_LOOP = '{' STRUCT_BODY* '}'
*/
-static THROWABLE parser_parse_struct_body_loop(Parser *self, Scope *scope) {
+static void parser_parse_struct_body_loop(Parser *self, Scope *scope) {
int result;
throw_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_BRACE));
for(;;) {
- Ast body_obj;
+ Ast *body_obj;
bool is_end_token;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_BRACE, &is_end_token));
if(is_end_token)
break;
- try(parser_parse_struct_body(self, &body_obj));
- result = scope_add_child(scope, &body_obj);
+ body_obj = parser_parse_struct_body(self);
+ result = scope_add_child(scope, body_obj);
if(result == 0) {
continue;
} else if(result == AST_ERR_DEF_DUP) {
/* TODO: Convert ast type to string for error message */
BufferView obj_name;
- obj_name = ast_get_name(&body_obj);
+ obj_name = ast_get_name(body_obj);
self->error = tokenizer_create_error(&self->tokenizer,
tokenizer_get_code_reference_index(&self->tokenizer, obj_name.data),
"Variable with the name %.*s was declared twice in the struct", obj_name.size, obj_name.data);
@@ -141,32 +127,32 @@ static THROWABLE parser_parse_struct_body_loop(Parser *self, Scope *scope) {
throw(result);
}
}
- return PARSER_OK;
}
/*
VAR_TYPE_DEF = ':' TOK_IDENTIFIER
*/
-static THROWABLE parser_parse_var_type_def(Parser *self, BufferView *type_name) {
+static void parser_parse_var_type_def(Parser *self, BufferView *type_name) {
bool match;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_COLON, &match));
if(match) {
throw_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER));
*type_name = self->tokenizer.value.identifier;
}
- return PARSER_OK;
}
/*
-LHS = ('const' TOK_IDENTIFIER VAR_TYPE_DEF? '=') |
- ('var' TOK_IDENTIFIER VAR_TYPE_DEF? '='|';')
+LHS = ('pub'? 'const' TOK_IDENTIFIER VAR_TYPE_DEF? '=') |
+ ('pub'? 'var' TOK_IDENTIFIER VAR_TYPE_DEF? '='|';')
*/
-static THROWABLE parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignment_or_rhs) {
+static CHECK_RESULT LhsExpr* parser_parse_lhs(Parser *self, bool *assignment_or_rhs) {
+ LhsExpr *result;
bool is_pub;
bool is_const;
bool match;
BufferView var_name;
- *result = NULL;
+
+ result = NULL;
*assignment_or_rhs = bool_true;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_PUB, &is_pub));
@@ -182,23 +168,23 @@ static THROWABLE parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignme
bool isVar;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_VAR, &isVar));
if(!isVar)
- return PARSER_OK;
+ return result;
}
throw_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER));
var_name = self->tokenizer.value.identifier;
- throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)result));
- throw_if_error(lhsexpr_init(*result, is_pub, is_const, var_name, self->allocator));
+ throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)&result));
+ throw_if_error(lhsexpr_init(result, is_pub, is_const, var_name, self->allocator));
- try(parser_parse_var_type_def(self, &(*result)->type.name));
+ parser_parse_var_type_def(self, &result->type.name);
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_EQUALS, &match));
if(match) {
*assignment_or_rhs = bool_true;
- return PARSER_OK;
+ return result;
}
- if(!(*result)->type.name.data) {
+ if(!result->type.name.data) {
self->error = tokenizer_create_error(&self->tokenizer,
tokenizer_get_error_index(&self->tokenizer),
"Variable declaration requires type or right-hand side expression (Expected ':' or '=')");
@@ -219,20 +205,21 @@ static THROWABLE parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignme
"Expected ';'");
throw(PARSER_UNEXPECTED_TOKEN);
}
- return PARSER_OK;
+ return result;
}
/*
-TODO: Implement params
+TODO: Implement params and return types
CLOSURE = 'fn' ('(' PARAM* ')')? '{' BODY_LOOP '}'
*/
-static THROWABLE parser_parse_function_decl(Parser *self, FunctionDecl **func_decl) {
+static CHECK_RESULT FunctionDecl* parser_parse_closure(Parser *self) {
+ FunctionDecl *result;
bool match;
- *func_decl = NULL;
+ result = NULL;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_FN, &match));
if(!match)
- return PARSER_OK;
+ return result;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_BRACE, &match));
if(!match) {
@@ -243,46 +230,47 @@ static THROWABLE parser_parse_function_decl(Parser *self, FunctionDecl **func_de
throw_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_BRACE));
}
- throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionDecl), (void**)func_decl));
- throw_if_error(funcdecl_init(*func_decl, self->current_scope, self->allocator));
+ throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionDecl), (void**)&result));
+ throw_if_error(funcdecl_init(result, self->current_scope, self->allocator));
- self->current_scope = &(*func_decl)->body;
- try(parser_parse_body_loop(self, self->current_scope, TOK_CLOSING_BRACE));
- self->current_scope = (*func_decl)->body.parent;
- return PARSER_OK;
+ self->current_scope = &result->body;
+ parser_parse_body_loop(self, self->current_scope, TOK_CLOSING_BRACE);
+ self->current_scope = result->body.parent;
+ return result;
}
/*
STRUCT = 'struct' '{' STRUCT_BODY_LOOP '}'
*/
-static THROWABLE parser_parse_struct_decl(Parser *self, StructDecl **struct_decl) {
+static CHECK_RESULT StructDecl* parser_parse_struct_decl(Parser *self) {
+ StructDecl *result;
bool match;
- *struct_decl = NULL;
+ result = NULL;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_STRUCT, &match));
if(!match)
- return PARSER_OK;
+ return result;
- throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(StructDecl), (void**)struct_decl));
- throw_if_error(structdecl_init(*struct_decl, self->current_scope, self->allocator));
+ throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(StructDecl), (void**)&result));
+ throw_if_error(structdecl_init(result, self->current_scope, self->allocator));
- self->current_scope = &(*struct_decl)->body;
- try(parser_parse_struct_body_loop(self, self->current_scope));
- self->current_scope = (*struct_decl)->body.parent;
- return PARSER_OK;
+ self->current_scope = &result->body;
+ parser_parse_struct_body_loop(self, self->current_scope);
+ self->current_scope = result->body.parent;
+ return result;
}
/*
FUNC_ARGS = (RHS_START)? (',' RHS_START)* ')'
*/
-static THROWABLE parser_parse_function_args(Parser *self, FunctionCall *func_call) {
+static void parser_parse_function_args(Parser *self, FunctionCall *func_call) {
bool first_arg;
first_arg = bool_true;
for(;;) {
- Ast arg_expr;
+ Ast *arg_expr;
bool is_end_token;
- arg_expr = ast_none();
+ arg_expr = NULL;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_PAREN, &is_end_token));
if(is_end_token)
@@ -292,25 +280,25 @@ static THROWABLE parser_parse_function_args(Parser *self, FunctionCall *func_cal
throw_if_error(tokenizer_accept(&self->tokenizer, TOK_COMMA));
first_arg = bool_false;
- try(parser_parse_rhs_start(self, &arg_expr, bool_false));
+ arg_expr = parser_parse_rhs_start(self, bool_false);
throw_if_error(buffer_append(&func_call->args, &arg_expr, sizeof(arg_expr)));
}
-
- return PARSER_OK;
}
/*
VARIABLE = TOK_IDENTIFIER
FUNC_CALL_OR_VARIABLE = VARIABLE '(' FUNC_ARGS ')'
*/
-static THROWABLE parser_parse_function_call_or_variable(Parser *self, Ast *expr) {
+static CHECK_RESULT Ast* parser_parse_function_call_or_variable(Parser *self) {
+ Ast *result;
bool match;
BufferView identifier;
FunctionCall *func_call;
+ result = NULL;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IDENTIFIER, &match));
if(!match)
- return PARSER_OK;
+ return result;
identifier = self->tokenizer.value.identifier;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, &match));
@@ -318,70 +306,74 @@ static THROWABLE parser_parse_function_call_or_variable(Parser *self, Ast *expr)
Variable *variable;
throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Variable), (void**)&variable));
variable_init(variable, identifier);
- ast_init(expr, variable, AST_VARIABLE);
- return PARSER_OK;
+ throw_if_error(ast_create(self->allocator, variable, AST_VARIABLE, &result));
+ return result;
}
throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionCall), (void**)&func_call));
throw_if_error(funccall_init(func_call, self->tokenizer.value.identifier, self->allocator));
- ast_init(expr, func_call, AST_FUNCTION_CALL);
- try(parser_parse_function_args(self, func_call));
- return PARSER_OK;
+ throw_if_error(ast_create(self->allocator, func_call, AST_FUNCTION_CALL, &result));
+ parser_parse_function_args(self, func_call);
+ return result;
}
/*
IMPORT = IMPORT_SYMBOL
*/
-static THROWABLE parser_parse_import(Parser *self, Import **import) {
+static CHECK_RESULT Import* parser_parse_import(Parser *self) {
+ Import *result;
bool match;
- *import = NULL;
+ result = NULL;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IMPORT, &match));
if(!match)
- return PARSER_OK;
+ return result;
- throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Import), (void**)import));
- import_init(*import, self->tokenizer.value.string);
- return PARSER_OK;
+ throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Import), (void**)&result));
+ import_init(result, self->tokenizer.value.string);
+ return result;
}
-static THROWABLE parser_parse_number(Parser *self, Ast *rhs_expr) {
+static CHECK_RESULT Ast* parser_parse_number(Parser *self) {
+ Ast *result;
bool match;
Number *number;
+ result = NULL;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_NUMBER, &match));
if(!match)
- return PARSER_OK;
+ return result;
throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Number), (void**)&number));
number_init(number, self->tokenizer.value.integer, self->tokenizer.number_is_integer);
- ast_init(rhs_expr, number, AST_NUMBER);
- return PARSER_OK;
+ throw_if_error(ast_create(self->allocator, number, AST_NUMBER, &result));
+ return result;
}
/*
RHS_S = STRING | NUMBER | FUNC_CALL_OR_VARIABLE
*/
-static THROWABLE parser_parse_rhs_single_expr(Parser *self, Ast *rhs_expr) {
+static Ast* parser_parse_rhs_single_expr(Parser *self) {
+ Ast *result;
bool match;
- *rhs_expr = ast_none();
+ result = NULL;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_STRING, &match));
if(match) {
String *string;
throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(String), (void**)&string));
throw_if_error(string_init(string, self->tokenizer.value.string));
- ast_init(rhs_expr, string, AST_STRING);
- return PARSER_OK;
+ throw_if_error(ast_create(self->allocator, string, AST_STRING, &result));
+ return result;
}
- try(parser_parse_number(self, rhs_expr));
- if(rhs_expr->type != AST_NONE)
- return PARSER_OK;
+ result = parser_parse_number(self);
+ if(result)
+ return result;
- try(parser_parse_function_call_or_variable(self, rhs_expr));
- if(rhs_expr->type != AST_NONE)
- return PARSER_OK;
+ result = parser_parse_function_call_or_variable(self);
+ if(result)
+ return result;
self->error = tokenizer_create_error(&self->tokenizer,
tokenizer_get_error_index(&self->tokenizer),
@@ -389,25 +381,24 @@ static THROWABLE parser_parse_rhs_single_expr(Parser *self, Ast *rhs_expr) {
throw(PARSER_UNEXPECTED_TOKEN);
}
-static THROWABLE parser_parse_rhs_binop(Parser *self, Ast *expr);
+static CHECK_RESULT Ast* parser_parse_rhs_binop(Parser *self);
/*
RHS_BINOP_OPT_PAREN = RHS_S | '(' RHS_BINOP ')'
*/
-static THROWABLE parser_parse_rhs_binop_opt_paren(Parser *self, Ast *expr) {
+static CHECK_RESULT Ast* parser_parse_rhs_binop_opt_paren(Parser *self) {
+ Ast *result;
bool match;
+
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, &match));
- if(!match) {
- try(parser_parse_rhs_single_expr(self, expr));
- return PARSER_OK;
- }
+ if(!match)
+ return parser_parse_rhs_single_expr(self);
- try(parser_parse_rhs_binop(self, expr));
+ result = parser_parse_rhs_binop(self);
throw_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN));
- if(expr->type == AST_BINOP)
- expr->value.binop->grouped = bool_true;
-
- return PARSER_OK;
+ if(result->type == AST_BINOP)
+ result->value.binop->grouped = bool_true;
+ return result;
}
/*
@@ -415,29 +406,28 @@ RHS_BINOP = RHS_BINOP_OPT_PAREN (TOK_BINOP RHS_BINOP_OPT_PAREN)?
Note: Parantheses count has to match for the beginning paranthesis and the ending parenthesis.
*/
-int parser_parse_rhs_binop(Parser *self, Ast *expr) {
+Ast* parser_parse_rhs_binop(Parser *self) {
bool match;
- Ast lhs;
- Ast rhs;
+ Ast *result;
+ Ast *lhs;
+ Ast *rhs;
BinopType binop_type;
Binop *binop;
- try(parser_parse_rhs_binop_opt_paren(self, &lhs));
+ lhs = parser_parse_rhs_binop_opt_paren(self);
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &match));
- if(!match) {
- *expr = lhs;
- return PARSER_OK;
- }
+ if(!match)
+ return lhs;
binop_type = self->tokenizer.value.binop_type;
- try(parser_parse_rhs_binop(self, &rhs));
+ rhs = parser_parse_rhs_binop(self);
throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Binop), (void**)&binop));
binop_init(binop);
binop->type = binop_type;
binop->lhs = lhs;
binop->rhs = rhs;
- ast_init(expr, binop, AST_BINOP);
- return PARSER_OK;
+ throw_if_error(ast_create(self->allocator, binop, AST_BINOP, &result));
+ return result;
}
/*
@@ -445,48 +435,51 @@ RHS = RHS_BINOP ';'
Note: Parantheses count has to match for the beginning paranthesis and the ending parenthesis.
*/
-static THROWABLE parser_parse_rhs(Parser *self, Ast *rhs_expr) {
+static CHECK_RESULT Ast* parser_parse_rhs(Parser *self) {
/* TODO: If binop only contains one expression, then use that directly for @rhs_expr */
- try(parser_parse_rhs_binop(self, rhs_expr));
+ Ast *result;
+ result = parser_parse_rhs_binop(self);
/* TODO: Implement this */
/*binop_reorder_by_precedence(binop);*/
- return PARSER_OK;
+ return result;
}
/*
RHS_START = CLOSURE | IMPORT | RHS
*/
-int parser_parse_rhs_start(Parser *self, Ast *rhs_expr, bool is_standalone) {
- FunctionDecl *func_decl;
- StructDecl *struct_decl;
- Import *import;
+Ast* parser_parse_rhs_start(Parser *self, bool is_standalone) {
+ Ast *result;
if(!is_standalone) {
- try(parser_parse_function_decl(self, &func_decl));
+ FunctionDecl *func_decl;
+ StructDecl *struct_decl;
+ Import *import;
+
+ func_decl = parser_parse_closure(self);
if(func_decl) {
- ast_init(rhs_expr, func_decl, AST_FUNCTION_DECL);
- return PARSER_OK;
+ throw_if_error(ast_create(self->allocator, func_decl, AST_FUNCTION_DECL, &result));
+ return result;
}
- try(parser_parse_struct_decl(self, &struct_decl));
+ struct_decl = parser_parse_struct_decl(self);
if(struct_decl) {
- ast_init(rhs_expr, struct_decl, AST_STRUCT_DECL);
- return PARSER_OK;
+ throw_if_error(ast_create(self->allocator, struct_decl, AST_STRUCT_DECL, &result));
+ return result;
}
- try(parser_parse_import(self, &import));
+ import = parser_parse_import(self);
if(import) {
- try(parser_queue_file(self, import->path, &import->file_scope));
- ast_init(rhs_expr, import, AST_IMPORT);
- return PARSER_OK;
+ parser_queue_file(self, import->path, &import->file_scope);
+ throw_if_error(ast_create(self->allocator, import, AST_IMPORT, &result));
+ return result;
}
self->error_context = ERROR_CONTEXT_RHS_STANDALONE;
}
- try(parser_parse_rhs(self, rhs_expr));
+ result = parser_parse_rhs(self);
self->error_context = ERROR_CONTEXT_NONE;
- return PARSER_OK;
+ return result;
}
/*
@@ -494,7 +487,7 @@ BODY_SEMICOLON = ';'
Note: Semicolon is not required for closures, structs and tables
*/
-static THROWABLE parser_parse_body_semicolon(Parser *self, Ast *expr) {
+static void parser_parse_body_semicolon(Parser *self, Ast *expr) {
if(expr->type == AST_BINOP) {
bool match;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_SEMICOLON, &match));
@@ -505,14 +498,12 @@ static THROWABLE parser_parse_body_semicolon(Parser *self, Ast *expr) {
"Expected ';' or binop");
throw(PARSER_UNEXPECTED_TOKEN);
}
- return PARSER_OK;
+ return;
}
/* TODO: Check for tables */
if(expr->type != AST_FUNCTION_DECL && expr->type != AST_STRUCT_DECL)
throw_if_error(tokenizer_accept(&self->tokenizer, TOK_SEMICOLON));
-
- return PARSER_OK;
}
/*
@@ -520,37 +511,38 @@ BODY = LHS ';' |
(LHS '=' RHS_START BODY_SEMICOLON) |
(RHS_START BODY_SEMICOLON)
*/
-int parser_parse_body(Parser *self, Ast *ast) {
+Ast* parser_parse_body(Parser *self) {
bool assignment_or_rhs;
+ Ast *result;
LhsExpr *lhs_expr;
- Ast rhs_expr;
- rhs_expr = ast_none();
+ Ast *rhs_expr;
- try(parser_parse_lhs(self, &lhs_expr, &assignment_or_rhs));
+ lhs_expr = parser_parse_lhs(self, &assignment_or_rhs);
if(!assignment_or_rhs) {
- ast_init(ast, lhs_expr, AST_LHS);
- return PARSER_OK;
+ throw_if_error(ast_create(self->allocator, lhs_expr, AST_LHS, &result));
+ return result;
}
if(!lhs_expr)
self->error_context = ERROR_CONTEXT_NO_LHS;
- try(parser_parse_rhs_start(self, &rhs_expr, lhs_expr == NULL));
+ rhs_expr = parser_parse_rhs_start(self, !lhs_expr);
if(lhs_expr) {
lhs_expr->rhs_expr = rhs_expr;
- ast_init(ast, lhs_expr, AST_LHS);
+ throw_if_error(ast_create(self->allocator, lhs_expr, AST_LHS, &result));
} else {
- *ast = rhs_expr;
+ result = rhs_expr;
}
- try(parser_parse_body_semicolon(self, &rhs_expr));
- return PARSER_OK;
+ parser_parse_body_semicolon(self, rhs_expr);
+ return result;
}
/*
-STRUCT_BODY = LHS ';'
+STRUCT_BODY = TOK_IDENTIFIER ':' TOK_IDENTIFIER ';'
*/
-int parser_parse_struct_body(Parser *self, Ast *ast) {
+Ast* parser_parse_struct_body(Parser *self) {
+ Ast *result;
BufferView var_name;
BufferView type_name;
StructField *struct_field;
@@ -563,8 +555,8 @@ int parser_parse_struct_body(Parser *self, Ast *ast) {
throw_if_error(tokenizer_accept(&self->tokenizer, TOK_SEMICOLON));
throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)&struct_field));
structfield_init(struct_field, var_name, type_name);
- ast_init(ast, struct_field, AST_STRUCT_FIELD);
- return PARSER_OK;
+ throw_if_error(ast_create(self->allocator, struct_field, AST_STRUCT_FIELD, &result));
+ return result;
}
/*
@@ -575,7 +567,7 @@ int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_
throw_if_error(tokenizer_init(&self->tokenizer, self->allocator, code_buffer, buffer_name));
result = setjmp(self->parse_env);
if(result == 0)
- try(parser_parse_body_loop(self, &self->scope, TOK_END_OF_FILE));
+ parser_parse_body_loop(self, &self->scope, TOK_END_OF_FILE);
else if(self->error.str != NULL) {
switch(self->error_context) {
case ERROR_CONTEXT_NONE:
@@ -592,9 +584,8 @@ int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_
break;
}
}
- if(result != 0) {
- amal_log_info("Failed, reason: %d", result);
- }
+ if(result != 0)
+ amal_log_error("Failed, reason: %d", result);
return result;
}
@@ -626,14 +617,14 @@ static CHECK_RESULT int file_path_join(BufferView directory, BufferView file, ch
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, FileScopeReference **file_scope) {
+void parser_queue_file(Parser *self, BufferView path, FileScopeReference **file_scope) {
/* TODO: Parse special path (to include library path with dots) */
BufferView file_directory;
char *path_relative;
int result;
file_directory = file_get_parent_directory(self->tokenizer.code_name);
- return_if_error(file_path_join(file_directory, path, &path_relative));
+ throw_if_error(file_path_join(file_directory, path, &path_relative));
/* We want buffer to be null-terminated but null character should not be included for the size */
result = amal_compiler_load_file(self->compiler, path_relative, file_scope);
if(result != 0) {
@@ -644,5 +635,4 @@ int parser_queue_file(Parser *self, BufferView path, FileScopeReference **file_s
throw(result);
}
am_free(path_relative);
- return PARSER_OK;
}
diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c
index b04e469..e55f687 100644
--- a/src/ssa/ssa.c
+++ b/src/ssa/ssa.c
@@ -256,15 +256,15 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom
static CHECK_RESULT SsaRegister funccall_generate_ssa(FunctionCall *self, SsaCompilerContext *context) {
/* TODO: Implement */
- Ast *ast;
- Ast *ast_end;
+ Ast **ast;
+ Ast **ast_end;
SsaRegister reg;
ast = buffer_start(&self->args);
ast_end = buffer_end(&self->args);
for(; ast != ast_end; ++ast) {
SsaRegister arg_reg;
- arg_reg = ast_generate_ssa(ast, context);
+ arg_reg = ast_generate_ssa(*ast, context);
throw_if_error(ssa_ins_push(&context->ssa, arg_reg));
}
/* TODO: Use real func index */
@@ -287,10 +287,16 @@ static CHECK_RESULT SsaRegister structfield_generate_ssa(StructField *self, SsaC
static CHECK_RESULT SsaRegister lhs_generate_ssa(LhsExpr *self, SsaCompilerContext *context) {
/* TODO: Implement */
- SsaRegister rhs_reg;
- rhs_reg = ast_generate_ssa(&self->rhs_expr, context);
- /* TODO: Is this correct? */
- return rhs_reg;
+ SsaRegister reg;
+ throw_if_error(ssa_get_unique_reg(&context->ssa, &reg));
+ if(self->rhs_expr) {
+ SsaRegister rhs_reg;
+ rhs_reg = ast_generate_ssa(self->rhs_expr, context);
+ throw_if_error(ssa_ins_assign_reg(&context->ssa, reg, rhs_reg));
+ } else {
+ /* TODO: assign default value to reg depending on LhsExpr type */
+ }
+ return reg;
}
static CHECK_RESULT SsaRegister string_generate_ssa(String *self, SsaCompilerContext *context) {
@@ -328,17 +334,21 @@ static CHECK_RESULT SsaRegister binop_generate_ssa(Binop *self, SsaCompilerConte
SsaRegister lhs_reg;
SsaRegister rhs_reg;
SsaRegister reg;
- lhs_reg = ast_generate_ssa(&self->lhs, context);
- rhs_reg = ast_generate_ssa(&self->rhs, context);
+ lhs_reg = ast_generate_ssa(self->lhs, context);
+ rhs_reg = ast_generate_ssa(self->rhs, context);
throw_if_error(ssa_ins_binop(&context->ssa, binop_type_to_ssa_type(self->type), lhs_reg, rhs_reg, &reg));
return reg;
}
CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context) {
- assert(self->resolve_status == AST_RESOLVED);
+ assert(self);
+ #ifdef DEBUG
+ if(self->resolve_data.status != AST_RESOLVED) {
+ amal_log_error("Ast type not resolved: %d", self->type);
+ assert(bool_false);
+ }
+ #endif
switch(self->type) {
- case AST_NONE:
- return 0;
case AST_NUMBER:
return number_generate_ssa(self->value.number, context);
case AST_FUNCTION_DECL:
@@ -365,11 +375,11 @@ CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context
}
void scope_generate_ssa(Scope *self, SsaCompilerContext *context) {
- Ast *ast;
- Ast *ast_end;
+ Ast **ast;
+ Ast **ast_end;
ast = buffer_start(&self->ast_objects);
ast_end = buffer_end(&self->ast_objects);
for(; ast != ast_end; ++ast) {
- ignore_result_int(ast_generate_ssa(ast, context));
+ ignore_result_int(ast_generate_ssa(*ast, context));
}
}