diff options
Diffstat (limited to 'src/ast.c')
-rw-r--r-- | src/ast.c | 121 |
1 files changed, 95 insertions, 26 deletions
@@ -20,6 +20,7 @@ Ast ast_none() { ast.value.func_decl = NULL; ast.type = AST_NONE; ast.resolve_status = AST_NOT_RESOLVED; + ast.resolved_type = NULL; return ast; } @@ -27,6 +28,7 @@ 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; } BufferView ast_get_name(Ast *self) { @@ -34,6 +36,7 @@ BufferView ast_get_name(Ast *self) { switch(self->type) { case AST_NONE: case AST_FUNCTION_DECL: + case AST_STRUCT_DECL: case AST_IMPORT: case AST_STRING: case AST_NUMBER: @@ -49,6 +52,9 @@ BufferView ast_get_name(Ast *self) { case AST_VARIABLE: name = self->value.variable->name; break; + case AST_STRUCT_FIELD: + name = self->value.struct_field->name; + break; } return name; } @@ -67,15 +73,25 @@ int funccall_init(FunctionCall *self, BufferView name, ScopedAllocator *allocato return buffer_init(&self->args, allocator); } -void lhsexpr_init(LhsExpr *self, int isConst, BufferView var_name) { - self->is_const = isConst; - self->type_name = create_buffer_view_null(); +int structdecl_init(StructDecl *self, Scope *parent, ScopedAllocator *allocator) { + return scope_init(&self->body, parent, allocator); +} + +void structfield_init(StructField *self, BufferView name, BufferView type_name) { + self->name = name; + variable_init(&self->type, type_name); +} + +void lhsexpr_init(LhsExpr *self, 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(); } void import_init(Import *self, BufferView path) { self->path = path; + self->file_scope = NULL; } int string_init(String *self, BufferView str) { @@ -108,6 +124,19 @@ int scope_init(Scope *self, Scope *parent, ScopedAllocator *allocator) { return 0; } +int file_scope_reference_init(FileScopeReference *self, BufferView canonical_path, ScopedAllocator *allocator) { + char null_terminator; + null_terminator = '\0'; + self->scope = NULL; + + return_if_error(buffer_init(&self->canonical_path, allocator)); + return_if_error(buffer_append(&self->canonical_path, canonical_path.data, canonical_path.size)); + return_if_error(buffer_append(&self->canonical_path, &null_terminator, 1)); + /* To exclude null-terminator character from size but not from data */ + self->canonical_path.size -= 1; + return 0; +} + int scope_add_child(Scope *self, Ast *child) { Ast existing_child; bool child_already_exists; @@ -132,16 +161,14 @@ int scope_add_child(Scope *self, Ast *child) { void scope_resolve(Scope *self, AstCompilerContext *context) { Ast *ast; Ast *ast_end; - Scope *prev_scope = context->scope; + ast = buffer_start(&self->ast_objects); ast_end = buffer_end(&self->ast_objects); - assert(self->parent == context->scope); context->scope = self; for(; ast != ast_end; ++ast) { ast_resolve(ast, context); } context->scope = self->parent; - assert(context->scope == prev_scope); } static Ast scope_get_resolved_variable(Scope *self, AstCompilerContext *context, BufferView name) { @@ -155,7 +182,6 @@ static Ast scope_get_resolved_variable(Scope *self, AstCompilerContext *context, if(self->parent) return scope_get_resolved_variable(self->parent, context, name); - tokenizer_get_code_reference_index(&context->parser->tokenizer, name.data); tokenizer_print_error(&context->parser->tokenizer, tokenizer_get_code_reference_index(&context->parser->tokenizer, name.data), "Undefined reference to variable \"%.*s\"", name.size, name.data); @@ -176,23 +202,46 @@ static Ast scope_get_resolved_variable(Scope *self, AstCompilerContext *context, return result.value.lhs_expr->rhs_expr; } -static void variable_resolve(Variable *self, AstCompilerContext *context) { - /* TODO: Implement */ - amal_log_debug("variable resolve, var name: %.*s", self->name.size, self->name.data); +static void variable_resolve(Variable *self, AstCompilerContext *context, StructDecl **resolved_type) { self->resolved_variable = scope_get_resolved_variable(context->scope, context, self->name); + /* TODO: Implement */ + if(self->resolved_variable.type == AST_STRUCT_DECL) { + *resolved_type = self->resolved_variable.value.struct_decl; + } else if(self->resolved_variable.type == AST_FUNCTION_DECL) { + /* TODO: Set resolved type to function declaration return type */ + *resolved_type = NULL; + } else { + *resolved_type = NULL; + } } static void lhs_resolve(Ast *self, AstCompilerContext *context) { - /* TODO: Implement */ LhsExpr *lhs_expr; - assert(self->type == AST_LHS); lhs_expr = self->value.lhs_expr; - amal_log_debug("Lhs resolve %s name: %.*s, type: %.*s", - lhs_expr->is_const ? "const" : "var", - lhs_expr->var_name.size, lhs_expr->var_name.data, - lhs_expr->type_name.size, lhs_expr->type_name.data); + + 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); + + 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); + } + self->resolved_type = lhs_expr->rhs_expr.resolved_type; +} + +static void import_resolve(Ast *self, AstCompilerContext *context) { + Import *import; + import = self->value.import; + (void)import; + (void)self; + (void)context; + /* TODO: Implement parser scope for import */ } static void funcdecl_resolve(Ast *self, AstCompilerContext *context) { @@ -200,26 +249,40 @@ static void funcdecl_resolve(Ast *self, AstCompilerContext *context) { FunctionDecl *func_decl; assert(self->type == AST_FUNCTION_DECL); func_decl = self->value.func_decl; - amal_log_debug("funcdecl resolve"); self->resolve_status = AST_RESOLVED; scope_resolve(&func_decl->body, context); } -static void funccall_resolve(FunctionCall *self, AstCompilerContext *context) { - /* TODO: Implement */ +static void funccall_resolve(Ast *self, AstCompilerContext *context) { + FunctionCall *func_call; Ast *ast; Ast *ast_end; - variable_resolve(&self->func, context); + func_call = self->value.func_call; + variable_resolve(&func_call->func, context, &self->resolved_type); - ast = buffer_start(&self->args); - ast_end = buffer_end(&self->args); - amal_log_debug("funccall resolve, func name: %.*s", self->func.name.size, self->func.name.data); + ast = buffer_start(&func_call->args); + ast_end = buffer_end(&func_call->args); for(; ast != ast_end; ++ast) { ast_resolve(ast, context); } } +static void structdecl_resolve(Ast *self, AstCompilerContext *context) { + /* TODO: Implement */ + StructDecl *struct_decl; + struct_decl = self->value.struct_decl; + self->resolved_type = struct_decl; + scope_resolve(&struct_decl->body, context); +} + +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); +} + static void binop_resolve(Binop *self, AstCompilerContext *context) { /* TODO: Implement */ ast_resolve(&self->lhs, context); @@ -237,7 +300,6 @@ void ast_resolve(Ast *self, AstCompilerContext *context) { if(self->resolve_status == AST_RESOLVED) { return; } else if(self->resolve_status == AST_RESOLVING) { - tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data); tokenizer_print_error(&context->parser->tokenizer, tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data), "Found recursive dependency"); @@ -254,19 +316,26 @@ void ast_resolve(Ast *self, AstCompilerContext *context) { funcdecl_resolve(self, context); break; case AST_FUNCTION_CALL: - funccall_resolve(self->value.func_call, context); + funccall_resolve(self, context); + break; + case AST_STRUCT_DECL: + structdecl_resolve(self, context); + break; + case AST_STRUCT_FIELD: + structfield_resolve(self, context); break; case AST_LHS: lhs_resolve(self, context); break; case AST_IMPORT: /* TODO: When @import(...).data syntax is added, implement the resolve for it */ + import_resolve(self, context); break; case AST_STRING: /* TODO: Convert special combinations. For example \n to newline */ break; case AST_VARIABLE: - variable_resolve(self->value.variable, context); + variable_resolve(self->value.variable, context, &self->resolved_type); break; case AST_BINOP: binop_resolve(self->value.binop, context); |