aboutsummaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c149
1 files changed, 111 insertions, 38 deletions
diff --git a/src/ast.c b/src/ast.c
index 76cbf9c..912b9c7 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -296,9 +296,17 @@ int funccall_init(FunctionCall *self, BufferView name, ArenaAllocator *allocator
}
int structdecl_init(StructDecl *self, Scope *parent, ArenaAllocator *allocator) {
+ self->fields_num_pointers = 0;
+ self->fields_fixed_size_bytes = 0;
return scope_init(&self->body, parent, allocator);
}
+int structdecl_add_field(StructDecl *self, StructField *field, ArenaAllocator *allocator) {
+ Ast *body_obj;
+ return_if_error(ast_create(allocator, field, AST_STRUCT_FIELD, &body_obj));
+ return scope_add_child(&self->body, body_obj);
+}
+
LhsExpr* structdecl_get_field_by_name(StructDecl *self, BufferView field_name) {
Ast* result;
if(!hash_map_get(&self->body.named_objects, field_name, &result))
@@ -431,17 +439,16 @@ void scope_resolve(Scope *self, AstCompilerContext *context) {
}
static void compiler_print_error(amal_compiler *compiler, const char *ref, const char *fmt, ...) {
- Tokenizer *tokenizer = amal_compiler_find_tokenizer_by_code_reference(compiler, ref);
+ Tokenizer *tokenizer;
+ va_list args;
+ va_start(args, fmt);
+
+ tokenizer = amal_compiler_find_tokenizer_by_code_reference(compiler, ref);
if(!tokenizer) {
amal_log_error("Failed to find tokenizer for code reference %p. Is it an invalid reference?", ref ? ref : "(null)");
return;
}
-
- va_list args;
- va_start(args, fmt);
- tokenizer_print_error_args(tokenizer,
- tokenizer_get_code_reference_index(tokenizer, ref),
- fmt, args);
+ tokenizer_print_error_args(tokenizer, tokenizer_get_code_reference_index(tokenizer, ref), fmt, args);
va_end(args);
}
@@ -672,19 +679,20 @@ static void import_resolve(Ast *ast, AstCompilerContext *context) {
(void)context;
self = ast->value.import;
ast->resolve_data.type.type = RESOLVED_TYPE_LHS_EXPR;
- ast->resolve_data.type.value.lhs_expr = &self->file_scope->parser->file_decl;
+ ast->resolve_data.type.value.lhs_expr = &self->file_scope->file_scope_ref->parser->file_decl;
}
static Scope* lhsexpr_get_scope(LhsExpr *self) {
- AstValue value;
- value = self->rhs_expr->value;
+ AstValue value = self->rhs_expr->value;
switch(self->rhs_expr->type) {
case AST_FUNCTION_DECL:
return &value.func_decl->body;
case AST_STRUCT_DECL:
return &value.struct_decl->body;
case AST_IMPORT:
- return &value.import->file_scope->parser->struct_decl.body;
+ /* *import_index = 1 + value.import->file_scope->import_index;*/
+ assert(bool_false);
+ return &value.import->file_scope->file_scope_ref->parser->struct_decl.body;
default:
break;
}
@@ -715,25 +723,11 @@ static void funcdecl_resolve(Ast *self, AstCompilerContext *context) {
self->resolve_data.type.value.func_sig = self->value.func_decl->signature;
}
-/*
- Dont need to check if @self is resolved, since it will always be partially resolved when called from @funccall_resolve.
- Meaning the resolve status wont be set to solved but the resolve type will be set.
-*/
-bool resolved_type_is_func_decl(Ast *self) {
- LhsExpr *resolved_type;
- if(self->resolve_data.type.type != RESOLVED_TYPE_LHS_EXPR)
- return bool_false;
- resolved_type = self->resolve_data.type.value.lhs_expr;
- return (resolved_type->rhs_expr && resolved_type->rhs_expr->type == AST_FUNCTION_DECL) ||
- resolved_type->type.type == VARIABLE_TYPE_SIGNATURE;
-}
-
static void funccall_resolve(Ast *self, AstCompilerContext *context) {
- FunctionCall *func_call;
Ast **ast;
Ast **ast_end;
- func_call = self->value.func_call;
+ FunctionCall *func_call = self->value.func_call;
variable_resolve(&func_call->func, context, &self->resolve_data.type);
/* Attemping to use call syntax (variable_name ( ) ) with a variable that is not a function */
if(self->resolve_data.type.type != RESOLVED_TYPE_FUNC_SIG) {
@@ -753,16 +747,46 @@ static void funccall_resolve(Ast *self, AstCompilerContext *context) {
}
}
+static TypeSize variable_type_get_byte_size(VariableType *self) {
+ TypeSize type_size;
+ type_size.num_pointers = 0;
+ type_size.fixed_size = 0;
+ switch(self->type) {
+ case VARIABLE_TYPE_NONE:
+ break;
+ case VARIABLE_TYPE_VARIABLE:
+ type_size = resolved_type_get_byte_size(&self->value.variable->resolved_var.resolve_data->type);
+ break;
+ case VARIABLE_TYPE_SIGNATURE:
+ type_size.num_pointers = 1;
+ break;
+ }
+ return type_size;
+}
+
static void structdecl_resolve(Ast *self, AstCompilerContext *context) {
- StructDecl *struct_decl;
- struct_decl = self->value.struct_decl;
- scope_resolve(&struct_decl->body, context);
+ StructDecl *struct_decl = self->value.struct_decl;
+ Scope *body = &struct_decl->body;
+ scope_resolve(body, context);
+
+ {
+ /*
+ Sum the size of all the fields into the struct, so the struct can know it's full size
+ without searching for it.
+ TODO: Exclude functions, but not function pointers.
+ */
+ Ast **ast = buffer_begin(&body->ast_objects);
+ Ast **ast_end = buffer_end(&body->ast_objects);
+ for(; ast != ast_end; ++ast) {
+ TypeSize type_size = variable_type_get_byte_size(&(*ast)->value.struct_field->type);
+ struct_decl->fields_num_pointers += type_size.num_pointers;
+ struct_decl->fields_fixed_size_bytes += type_size.fixed_size;
+ }
+ }
}
static void structfield_resolve(Ast *self, AstCompilerContext *context) {
- /* TODO: Implement */
- StructField *struct_field;
- struct_field = self->value.struct_field;
+ StructField *struct_field = self->value.struct_field;
variable_type_resolve(&struct_field->type, context, &self->resolve_data.type);
}
@@ -806,12 +830,30 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) {
throw(AST_ERR);
}
- if(self->rhs->resolve_data.type.type != RESOLVED_TYPE_LHS_EXPR || !LHS_EXPR_IS_PUB(self->rhs->resolve_data.type.value.lhs_expr)) {
- compiler_print_error(context->compiler, 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 */
- compiler_print_error(context->compiler, callee_code_ref.data, "Type was declared non-public here");
- throw(AST_ERR);
+ {
+ bool invalid_dot_access = bool_true;
+ switch(self->rhs->resolve_data.type.type) {
+ case RESOLVED_TYPE_NONE:
+ assert(bool_false);
+ break;
+ case RESOLVED_TYPE_FUNC_SIG: {
+ FunctionSignature *func_sig = self->rhs->resolve_data.type.value.func_sig;
+ if(func_sig->func_decl && func_sig->func_decl->lhs_expr && LHS_EXPR_IS_PUB(func_sig->func_decl->lhs_expr))
+ invalid_dot_access = bool_false;
+ break;
+ }
+ case RESOLVED_TYPE_LHS_EXPR:
+ invalid_dot_access = !LHS_EXPR_IS_PUB(self->rhs->resolve_data.type.value.lhs_expr);
+ break;
+ }
+
+ if(invalid_dot_access) {
+ compiler_print_error(context->compiler, 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 */
+ compiler_print_error(context->compiler, callee_code_ref.data, "Type was declared non-public here");
+ throw(AST_ERR);
+ }
}
}
@@ -895,6 +937,37 @@ static void return_expr_resolve(ReturnExpr *self, AstCompilerContext *context) {
ast_resolve(self->rhs_expr, context);
}
+TypeSize resolved_type_get_byte_size(AstResolvedType *self) {
+ TypeSize type_size;
+ type_size.num_pointers = 0;
+ type_size.fixed_size = 0;
+ switch(self->type) {
+ case RESOLVED_TYPE_NONE:
+ break;
+ case RESOLVED_TYPE_LHS_EXPR: {
+ /* Resolved type until rhs is StructDecl or FunctionSignature */
+ LhsExpr *lhs_expr = self->value.lhs_expr;
+ if(lhs_expr->type.type != VARIABLE_TYPE_NONE)
+ type_size = variable_type_get_byte_size(&lhs_expr->type);
+ else {
+ assert(lhs_expr->rhs_expr);
+ if(lhs_expr->rhs_expr->type == AST_STRUCT_DECL) {
+ StructDecl *struct_decl = lhs_expr->rhs_expr->value.struct_decl;
+ type_size.num_pointers = struct_decl->fields_num_pointers;
+ type_size.fixed_size = struct_decl->fields_fixed_size_bytes;
+ } else {
+ type_size = resolved_type_get_byte_size(&lhs_expr->rhs_expr->resolve_data.type);
+ }
+ }
+ break;
+ }
+ case RESOLVED_TYPE_FUNC_SIG:
+ type_size.num_pointers = 1;
+ break;
+ }
+ return type_size;
+}
+
void ast_resolve(Ast *self, AstCompilerContext *context) {
assert(self);
assert(context->parser);