aboutsummaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c104
1 files changed, 60 insertions, 44 deletions
diff --git a/src/ast.c b/src/ast.c
index a2a927c..a9f9be2 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -180,6 +180,16 @@ void scope_resolve(Scope *self, AstCompilerContext *context) {
context->scope = self->parent;
}
+static Parser* scope_get_parser(Scope *scope) {
+ while(scope) {
+ if(scope->parser)
+ return scope->parser;
+ scope = scope->parent;
+ }
+ assert(bool_false && "BUG: At least some scope parent is supposed to have a parser");
+ return NULL;
+}
+
static Ast* scope_get_resolved_variable(Scope *self, AstCompilerContext *context, BufferView name) {
Ast *result;
bool exists;
@@ -188,11 +198,13 @@ static Ast* scope_get_resolved_variable(Scope *self, AstCompilerContext *context
assert(self);
exists = hash_map_get(&self->named_objects, name, &result);
if(!exists) {
+ Parser *parser;
if(self->parent)
return scope_get_resolved_variable(self->parent, context, name);
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, name.data),
+ parser = scope_get_parser(self);
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, name.data),
"Undefined reference to variable \"%.*s\"", name.size, name.data);
throw(AST_ERR);
}
@@ -216,13 +228,13 @@ static void variable_resolve(Variable *self, AstCompilerContext *context, AstRes
resolve_data->type = scope_get_resolved_variable(context->scope, context, self->name)->resolve_data.type;
}
-static LhsExpr* lhsexpr_resolve_rhs(Ast *ast, AstCompilerContext *context, LhsExpr *lhs_expr) {
+static LhsExpr* lhsexpr_resolve_rhs(LhsExpr *self, AstCompilerContext *context) {
LhsExpr *rhs_resolved_type;
- ast_resolve(ast, context);
- if(ast_is_decl(ast))
- rhs_resolved_type = lhs_expr;
+ ast_resolve(self->rhs_expr, context);
+ if(ast_is_decl(self->rhs_expr))
+ rhs_resolved_type = self;
else
- rhs_resolved_type = ast->resolve_data.type;
+ rhs_resolved_type = self->rhs_expr->resolve_data.type;
return rhs_resolved_type;
}
@@ -246,14 +258,14 @@ static void lhsexpr_resolve(Ast *ast, AstCompilerContext *context) {
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);
+ rhs_resolve_type = lhsexpr_resolve_rhs(self, context);
/* 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),
+ if(ast->resolve_data.type && self->rhs_expr && ast->resolve_data.type != rhs_resolve_type) {
+ Parser *parser;
+ parser = scope_get_parser(context->scope);
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, self->type.name.data),
"Variable type and variable assignment type (right-hand side) do not match");
throw(AST_ERR);
}
@@ -289,17 +301,10 @@ static Scope* lhsexpr_get_scope(LhsExpr *self) {
return NULL;
}
-/* @self has to be resolved before calling this */
+/* @self has to have a resolved type before calling this */
static Parser* get_resolved_type_parser(Ast *self) {
- Scope *scope;
- scope = lhsexpr_get_scope(self->resolve_data.type);
- while(scope) {
- if(scope->parser)
- return scope->parser;
- scope = scope->parent;
- }
- assert(bool_false && "BUG: At least some parent is supposed to have a parser");
- return NULL;
+ assert(self->resolve_data.type);
+ return scope_get_parser(lhsexpr_get_scope(self->resolve_data.type));
}
static void funcdecl_resolve(FunctionDecl *self, AstCompilerContext *context) {
@@ -315,17 +320,20 @@ static void funccall_resolve(Ast *self, AstCompilerContext *context) {
func_call = self->value.func_call;
variable_resolve(&func_call->func, context, &self->resolve_data);
if(self->resolve_data.type->rhs_expr->type != AST_FUNCTION_DECL) {
+ Parser *caller_parser;
Parser *callee_parser;
BufferView callee_code_ref;
+
+ caller_parser = scope_get_parser(context->scope);
callee_parser = get_resolved_type_parser(self);
callee_code_ref = self->resolve_data.type->var_name;
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, func_call->func.name.data),
+ tokenizer_print_error(&caller_parser->tokenizer,
+ tokenizer_get_code_reference_index(&caller_parser->tokenizer, func_call->func.name.data),
"\"%.*s\" is not a function. Only functions can be called", func_call->func.name.size, func_call->func.name.data);
/* TODO: use tokenizer_print_note, once it has been added */
/* TODO: Print type */
- tokenizer_print_error(&context->parser->tokenizer,
+ tokenizer_print_error(&callee_parser->tokenizer,
tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data),
"Type was declared here");
throw(AST_ERR);
@@ -354,19 +362,21 @@ static void structfield_resolve(Ast *self, AstCompilerContext *context) {
static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) {
Binop *self;
Scope *lhs_scope;
+ Parser *caller_parser;
Parser *callee_parser;
BufferView caller_code_ref;
BufferView callee_code_ref;
assert(ast->type == AST_BINOP);
self = ast->value.binop;
+ caller_parser = scope_get_parser(context->scope);
if(self->lhs->type != AST_VARIABLE) {
/* TODO: Allow field access for numbers and string as well */
BufferView code_ref;
code_ref = ast_get_code_reference(self->lhs);
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, code_ref.data),
+ tokenizer_print_error(&caller_parser->tokenizer,
+ tokenizer_get_code_reference_index(&caller_parser->tokenizer, code_ref.data),
"Accessing fields is only applicable for variables");
throw(AST_ERR);
}
@@ -379,24 +389,24 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) {
callee_code_ref = self->rhs->resolve_data.type->var_name;
if(self->lhs->resolve_data.type->rhs_expr->type != AST_STRUCT_DECL) {
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, caller_code_ref.data),
+ tokenizer_print_error(&caller_parser->tokenizer,
+ tokenizer_get_code_reference_index(&caller_parser->tokenizer, caller_code_ref.data),
"Can only access field of structs");
/* TODO: use tokenizer_print_note, once it has been added */
/* TODO: Print type */
- tokenizer_print_error(&context->parser->tokenizer,
+ tokenizer_print_error(&callee_parser->tokenizer,
tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data),
"Type was declared here");
throw(AST_ERR);
}
if(!self->rhs->resolve_data.type->is_pub) {
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, caller_code_ref.data),
+ tokenizer_print_error(&caller_parser->tokenizer,
+ tokenizer_get_code_reference_index(&caller_parser->tokenizer, caller_code_ref.data),
"Can't access non-public field \"%.*s\"", caller_code_ref.size, caller_code_ref.data);
/* TODO: use tokenizer_print_note, once it has been added */
/* TODO: Print type */
- tokenizer_print_error(&context->parser->tokenizer,
+ tokenizer_print_error(&callee_parser->tokenizer,
tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data),
"Type was declared non-public here");
throw(AST_ERR);
@@ -425,17 +435,19 @@ static void binop_resolve(Ast *ast, AstCompilerContext *context) {
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->rhs).data),
+ Parser *parser;
+ parser = scope_get_parser(context->scope);
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->rhs).data),
"Can't cast type \"%.*s\" to type \"%.*s\"",
self->rhs->resolve_data.type->var_name.size, self->rhs->resolve_data.type->var_name.data,
self->lhs->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->lhs).data),
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->lhs).data),
"Left-hand side is of type %.*s",
self->lhs->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),
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&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);
@@ -460,8 +472,10 @@ void ast_resolve(Ast *self, AstCompilerContext *context) {
if(self->resolve_data.status == AST_RESOLVED) {
return;
} 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),
+ Parser *parser;
+ parser = scope_get_parser(context->scope);
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self).data),
"Found recursive dependency");
throw(AST_ERR);
}
@@ -472,9 +486,11 @@ void ast_resolve(Ast *self, AstCompilerContext *context) {
amal_mutex_tryunlock(self->value.lhs_expr->mutex);
return;
} else if(self->resolve_data.status == AST_RESOLVING) {
+ Parser *parser;
+ parser = scope_get_parser(context->scope);
amal_mutex_tryunlock(self->value.lhs_expr->mutex);
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data),
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self).data),
"Found recursive dependency");
throw(AST_ERR);
}