aboutsummaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c121
1 files changed, 95 insertions, 26 deletions
diff --git a/src/ast.c b/src/ast.c
index 9605b57..8e19819 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -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);