aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast.c61
-rw-r--r--src/parser.c16
-rw-r--r--src/ssa/ssa.c67
-rw-r--r--src/std/log.c2
4 files changed, 98 insertions, 48 deletions
diff --git a/src/ast.c b/src/ast.c
index 4ee0934..a2a927c 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -128,6 +128,7 @@ int scope_init(Scope *self, Scope *parent, ScopedAllocator *allocator) {
return_if_error(buffer_init(&self->ast_objects, allocator));
return_if_error(hash_map_init(&self->named_objects, allocator, sizeof(Ast*), hash_compare_string, amal_hash_string));
self->parent = parent;
+ self->parser = NULL;
return 0;
}
@@ -271,7 +272,6 @@ static void import_resolve(Ast *ast, AstCompilerContext *context) {
assert(ast->resolve_data.type);
}
-/* LhsExpr has to be resolved before this is called */
static Scope* lhsexpr_get_scope(LhsExpr *self) {
AstValue value;
value = self->rhs_expr->value;
@@ -289,6 +289,19 @@ static Scope* lhsexpr_get_scope(LhsExpr *self) {
return NULL;
}
+/* @self has to be resolved 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;
+}
+
static void funcdecl_resolve(FunctionDecl *self, AstCompilerContext *context) {
/* TODO: Implement parameters and return types */
scope_resolve(&self->body, context);
@@ -301,6 +314,22 @@ 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 *callee_parser;
+ BufferView callee_code_ref;
+ 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),
+ "\"%.*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_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data),
+ "Type was declared here");
+ throw(AST_ERR);
+ }
ast = buffer_start(&func_call->args);
ast_end = buffer_end(&func_call->args);
@@ -327,6 +356,7 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) {
Scope *lhs_scope;
Parser *callee_parser;
BufferView caller_code_ref;
+ BufferView callee_code_ref;
assert(ast->type == AST_BINOP);
self = ast->value.binop;
@@ -343,24 +373,20 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) {
lhs_scope = lhsexpr_get_scope(self->lhs->resolve_data.type);
self->rhs->resolve_data.type = scope_get_resolved_variable(lhs_scope, context, self->rhs->value.variable->name)->resolve_data.type;
- self->rhs->resolve_data.status = AST_RESOLVED;
- /*
- const io = @import("std.io");
- io.write ^
- ^-from this, to-'
- */
- if(self->lhs->resolve_data.type->rhs_expr->type == AST_IMPORT)
- callee_parser = self->lhs->resolve_data.type->rhs_expr->value.import->file_scope->parser;
-
+ callee_parser = get_resolved_type_parser(self->rhs);
caller_code_ref = ast_get_code_reference(self->rhs);
- callee_parser = context->parser;
+ callee_code_ref = self->rhs->resolve_data.type->var_name;
- if(self->rhs->resolve_data.type->rhs_expr->type != AST_STRUCT_DECL) {
- /* TODO: Add note where the referenced data was declared */
+ 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),
- "Can only access field of struct's");
+ "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_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data),
+ "Type was declared here");
throw(AST_ERR);
}
@@ -371,7 +397,7 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) {
/* TODO: use tokenizer_print_note, once it has been added */
/* TODO: Print type */
tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&callee_parser->tokenizer, caller_code_ref.data),
+ tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data),
"Type was declared non-public here");
throw(AST_ERR);
}
@@ -382,8 +408,11 @@ static void binop_resolve(Ast *ast, AstCompilerContext *context) {
assert(ast->type == AST_BINOP);
self = ast->value.binop;
ast_resolve(self->lhs, context);
- if(self->type == BINOP_DOT && self->rhs->type == AST_VARIABLE) {
+ if(self->type == BINOP_DOT && (self->rhs->type == AST_VARIABLE || self->rhs->type == AST_FUNCTION_CALL)) {
binop_resolve_dot_access(ast, context);
+ /* Only function call has extra data that needs to be resolved (args) */
+ if(self->rhs->type == AST_FUNCTION_CALL)
+ ast_resolve(self->rhs, context);
self->rhs->resolve_data.status = AST_RESOLVED;
ast->resolve_data.type = self->rhs->resolve_data.type;
} else {
diff --git a/src/parser.c b/src/parser.c
index 7b69ee7..bac7b3a 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -59,16 +59,14 @@ int parser_init(Parser *self, amal_compiler *compiler, ScopedAllocator *allocato
self->error.str = NULL;
self->error_context = ERROR_CONTEXT_NONE;
return_if_error(structdecl_init(&self->struct_decl, &compiler->root_scope, allocator));
+ self->struct_decl.body.parser = self;
return_if_error(lhsexpr_init(&self->file_decl, bool_true, bool_true, create_buffer_view_null(), self->allocator));
return_if_error(ast_create(self->allocator, &self->struct_decl, AST_STRUCT_DECL, &self->file_decl.rhs_expr));
self->current_scope = &self->struct_decl.body;
+ self->has_func_parent = bool_false;
return PARSER_OK;
}
-static bool parser_is_global_scope(Parser *self) {
- return self->current_scope == &self->struct_decl.body;
-}
-
/*
BODY_LOOP = BODY* @end_token
*/
@@ -159,10 +157,10 @@ static CHECK_RESULT LhsExpr* parser_parse_lhs(Parser *self, bool *assignment_or_
*assignment_or_rhs = bool_true;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_PUB, &is_pub));
- if(is_pub && !parser_is_global_scope(self)) {
+ if(is_pub && self->has_func_parent) {
self->error = tokenizer_create_error(&self->tokenizer,
tokenizer_get_code_reference_index(&self->tokenizer, self->tokenizer.value.identifier.data),
- "Only declarations in global scope can be public");
+ "Only declarations in structs can be public");
throw(PARSER_UNEXPECTED_TOKEN);
}
@@ -213,11 +211,12 @@ static CHECK_RESULT LhsExpr* parser_parse_lhs(Parser *self, bool *assignment_or_
/*
TODO: Implement params and return types
-CLOSURE = 'fn' ('(' PARAM* ')')? '{' BODY_LOOP '}'
+CLOSURE = 'fn' ('(' PARAM? (',' PARAM)* ')')? '{' BODY_LOOP '}'
*/
static CHECK_RESULT FunctionDecl* parser_parse_closure(Parser *self) {
FunctionDecl *result;
bool match;
+ bool prev_has_func_parent;
result = NULL;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_FN, &match));
@@ -237,8 +236,11 @@ static CHECK_RESULT FunctionDecl* parser_parse_closure(Parser *self) {
throw_if_error(funcdecl_init(result, self->current_scope, self->allocator));
self->current_scope = &result->body;
+ prev_has_func_parent = self->has_func_parent;
+ self->has_func_parent = bool_true;
parser_parse_body_loop(self, self->current_scope, TOK_CLOSING_BRACE);
self->current_scope = result->body.parent;
+ self->has_func_parent = prev_has_func_parent;
return result;
}
diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c
index e55f687..3fffb63 100644
--- a/src/ssa/ssa.c
+++ b/src/ssa/ssa.c
@@ -2,6 +2,7 @@
#include "../../include/std/mem.h"
#include "../../include/std/log.h"
#include "../../include/std/hash.h"
+#include "../../include/std/thread.h"
#include "../../include/ast.h"
#include <assert.h>
@@ -246,6 +247,27 @@ static CHECK_RESULT SsaRegister number_generate_ssa(Number *self, SsaCompilerCon
return reg;
}
+
+static CHECK_RESULT SsaRegister lhs_generate_ssa(LhsExpr *self, SsaCompilerContext *context) {
+ /* TODO: Implement */
+ SsaRegister reg;
+ throw_if_error(amal_mutex_lock(self->mutex, "lhs_generate_ssa"));
+ throw_if_error(ssa_get_unique_reg(&context->ssa, &reg));
+ if(self->rhs_expr) {
+ SsaRegister rhs_reg;
+ rhs_reg = ast_generate_ssa(self->rhs_expr, context);
+ throw_if_error(ssa_ins_assign_reg(&context->ssa, reg, rhs_reg));
+ } else {
+ /* TODO: assign default value to reg depending on LhsExpr type */
+ }
+ throw_if_error(amal_mutex_unlock(self->mutex));
+ return reg;
+}
+
+/*
+TODO: Each function declaration should be in separate SSA instances so ast can be converted into ssa
+in any order.
+*/
static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCompilerContext *context) {
/* TODO: Implement */
throw_if_error(ssa_ins_func_start(&context->ssa, 0, &self->ssa_func_index));
@@ -254,21 +276,27 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom
return 0;
}
-static CHECK_RESULT SsaRegister funccall_generate_ssa(FunctionCall *self, SsaCompilerContext *context) {
+static CHECK_RESULT SsaRegister funccall_generate_ssa(Ast *self, SsaCompilerContext *context) {
/* TODO: Implement */
+ FunctionCall *func_call;
Ast **ast;
Ast **ast_end;
SsaRegister reg;
- ast = buffer_start(&self->args);
- ast_end = buffer_end(&self->args);
+ assert(self->type == AST_FUNCTION_CALL);
+ func_call = self->value.func_call;
+ ast = buffer_start(&func_call->args);
+ ast_end = buffer_end(&func_call->args);
for(; ast != ast_end; ++ast) {
SsaRegister arg_reg;
arg_reg = ast_generate_ssa(*ast, context);
throw_if_error(ssa_ins_push(&context->ssa, arg_reg));
}
- /* TODO: Use real func index */
- throw_if_error(ssa_ins_call(&context->ssa, 0, &reg));
+
+ assert(self->resolve_data.type->rhs_expr->type == AST_FUNCTION_DECL);
+ ignore_result_int(lhs_generate_ssa(self->resolve_data.type, context));
+ amal_log_debug("SSA funccall %.*s, func index: %d", func_call->func.name.size, func_call->func.name.data, self->resolve_data.type->rhs_expr->value.func_decl->ssa_func_index);
+ throw_if_error(ssa_ins_call(&context->ssa, self->resolve_data.type->rhs_expr->value.func_decl->ssa_func_index, &reg));
return reg;
}
@@ -285,20 +313,6 @@ static CHECK_RESULT SsaRegister structfield_generate_ssa(StructField *self, SsaC
return 0;
}
-static CHECK_RESULT SsaRegister lhs_generate_ssa(LhsExpr *self, SsaCompilerContext *context) {
- /* TODO: Implement */
- SsaRegister reg;
- throw_if_error(ssa_get_unique_reg(&context->ssa, &reg));
- if(self->rhs_expr) {
- SsaRegister rhs_reg;
- rhs_reg = ast_generate_ssa(self->rhs_expr, context);
- throw_if_error(ssa_ins_assign_reg(&context->ssa, reg, rhs_reg));
- } else {
- /* TODO: assign default value to reg depending on LhsExpr type */
- }
- return reg;
-}
-
static CHECK_RESULT SsaRegister string_generate_ssa(String *self, SsaCompilerContext *context) {
SsaRegister reg;
throw_if_error(ssa_get_unique_reg(&context->ssa, &reg));
@@ -324,7 +338,7 @@ static SsaInstructionType binop_type_to_ssa_type(BinopType binop_type) {
case BINOP_DIV:
return SSA_DIV;
case BINOP_DOT:
- assert(bool_false && "TODO: Implement dot access");
+ assert(bool_false && "Binop dot not valid for arithmetic operation and requires special functionality");
return 0;
}
return 0;
@@ -334,9 +348,14 @@ static CHECK_RESULT SsaRegister binop_generate_ssa(Binop *self, SsaCompilerConte
SsaRegister lhs_reg;
SsaRegister rhs_reg;
SsaRegister reg;
- lhs_reg = ast_generate_ssa(self->lhs, context);
- rhs_reg = ast_generate_ssa(self->rhs, context);
- throw_if_error(ssa_ins_binop(&context->ssa, binop_type_to_ssa_type(self->type), lhs_reg, rhs_reg, &reg));
+
+ if(self->type == BINOP_DOT && self->rhs->resolve_data.type->rhs_expr->type == AST_FUNCTION_DECL) {
+ reg = ast_generate_ssa(self->rhs, context);
+ } else {
+ lhs_reg = ast_generate_ssa(self->lhs, context);
+ rhs_reg = ast_generate_ssa(self->rhs, context);
+ throw_if_error(ssa_ins_binop(&context->ssa, binop_type_to_ssa_type(self->type), lhs_reg, rhs_reg, &reg));
+ }
return reg;
}
@@ -354,7 +373,7 @@ CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context
case AST_FUNCTION_DECL:
return funcdecl_generate_ssa(self->value.func_decl, context);
case AST_FUNCTION_CALL:
- return funccall_generate_ssa(self->value.func_call, context);
+ return funccall_generate_ssa(self, context);
case AST_STRUCT_DECL:
return structdecl_generate_ssa(self->value.struct_decl, context);
case AST_STRUCT_FIELD:
diff --git a/src/std/log.c b/src/std/log.c
index 2059445..a03e62f 100644
--- a/src/std/log.c
+++ b/src/std/log.c
@@ -4,7 +4,7 @@
#include <stdio.h>
#include <stdarg.h>
-/*#define LOG_DEBUG*/
+#define LOG_DEBUG
static amal_mutex mutex;
static bool mutex_initialized = bool_false;