diff options
Diffstat (limited to 'src/ast.c')
-rw-r--r-- | src/ast.c | 149 |
1 files changed, 111 insertions, 38 deletions
@@ -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); |