aboutsummaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c75
1 files changed, 68 insertions, 7 deletions
diff --git a/src/ast.c b/src/ast.c
index 0008785..90af981 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -5,6 +5,7 @@
#include "../include/std/hash.h"
#include <assert.h>
#include <stdarg.h>
+#include <stdio.h>
#define throw(result) do { throw_debug_msg; longjmp(context->env, (result)); } while(0)
#define throw_if_error(result) \
@@ -446,6 +447,8 @@ static void compiler_print_error(amal_compiler *compiler, const char *ref, const
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)");
+ vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
return;
}
tokenizer_print_error_args(tokenizer, tokenizer_get_code_reference_index(tokenizer, ref), fmt, args);
@@ -726,9 +729,60 @@ static void funcdecl_resolve(Ast *self, AstCompilerContext *context) {
self->resolve_data.type.value.func_sig = self->value.func_decl->signature;
}
+static usize min(usize a, usize b) {
+ return a < b ? a : b;
+}
+
+static bool resolve_data_type_equals(AstResolvedType *self, AstResolvedType *other) {
+ return self->type == other->type && self->value.data == other->value.data;
+}
+
+static bool function_parameter_is_vararg(FunctionParameter *self, AstCompilerContext *context) {
+ amal_default_type *vararg_type = context->compiler->default_types.c_varargs;
+ return self->resolve_data.type.value.data == &vararg_type->lhs_expr;
+}
+
+static void verify_func_call_matches_func_signature(FunctionCall *func_call, FunctionSignature *func_sig, AstCompilerContext *context) {
+ Ast **arg = buffer_begin(&func_call->args);
+ Ast **arg_end = buffer_end(&func_call->args);
+
+ FunctionParameter *func_param = buffer_begin(&func_sig->parameters);
+ FunctionParameter *func_param_end = buffer_end(&func_sig->parameters);
+
+ usize num_args = arg_end - arg;
+ usize num_params = func_param_end - func_param;
+ isize num_missing_args = (isize)num_params - (isize)num_args;
+ usize num_check = min(num_args, num_params);
+ usize i = 0;
+ for(; i < num_check; ++i) {
+ if(!resolve_data_type_equals(&(*arg)->resolve_data.type, &func_param->resolve_data.type) && !function_parameter_is_vararg(func_param, context)) {
+ BufferView arg_name = ast_resolved_type_get_name(&(*arg)->resolve_data.type);
+ BufferView param_name = ast_resolved_type_get_name(&func_param->resolve_data.type);
+ compiler_print_error(context->compiler, func_call->func.name.data,
+ "Can't cast argument of type \"%.*s\" to parameter of type \"%.*s\"", arg_name.size, arg_name.data, param_name.size, param_name.data);
+ throw(AST_ERR);
+ }
+ ++arg;
+ ++func_param;
+ }
+
+ if(num_missing_args > 0) {
+ FunctionParameter *vararg_param = buffer_begin(&func_sig->parameters);
+ bool has_vararg = num_params > 0 && function_parameter_is_vararg(&vararg_param[num_params - 1], context);
+ if (has_vararg)
+ num_missing_args -= 1;
+ if(num_missing_args > 0) {
+ compiler_print_error(context->compiler, func_call->func.name.data,
+ "Missing %d argument(s) to closure \"%.*s\"", num_missing_args, func_call->func.name.size, func_call->func.name.data);
+ throw(AST_ERR);
+ }
+ }
+}
+
static void funccall_resolve(Ast *self, AstCompilerContext *context) {
Ast **ast;
Ast **ast_end;
+ FunctionSignature *func_sig;
FunctionCall *func_call = self->value.func_call;
variable_resolve(&func_call->func, context, &self->resolve_data.type);
@@ -744,7 +798,7 @@ static void funccall_resolve(Ast *self, AstCompilerContext *context) {
}
{
- FunctionSignature *func_sig = self->resolve_data.type.value.func_sig;
+ func_sig = self->resolve_data.type.value.func_sig;
FunctionReturnType *return_type = buffer_begin(&func_sig->return_types);
assert(buffer_get_size(&func_sig->return_types, FunctionReturnType) == 1);
self->resolve_data.type.type = RESOLVED_TYPE_LHS_EXPR;
@@ -756,6 +810,8 @@ static void funccall_resolve(Ast *self, AstCompilerContext *context) {
for(; ast != ast_end; ++ast) {
ast_resolve(*ast, context);
}
+
+ verify_func_call_matches_func_signature(func_call, func_sig, context);
}
static TypeSize variable_type_get_byte_size(VariableType *self) {
@@ -766,9 +822,13 @@ static TypeSize variable_type_get_byte_size(VariableType *self) {
case VARIABLE_TYPE_NONE:
assert(bool_false && "Variable type not resolved!");
break;
- case VARIABLE_TYPE_VARIABLE:
- type_size = resolved_type_get_byte_size(&self->value.variable->resolved_var.resolve_data->type);
+ case VARIABLE_TYPE_VARIABLE: {
+ if(self->variable_type_flags & VARIABLE_TYPE_FLAG_BORROW)
+ type_size.num_pointers = 1;
+ else
+ 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;
@@ -790,7 +850,8 @@ static void structdecl_resolve(Ast *self, AstCompilerContext *context) {
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);
+ StructField *struct_field = (*ast)->value.struct_field;
+ TypeSize type_size = variable_type_get_byte_size(&struct_field->type);
struct_decl->fields_num_pointers += type_size.num_pointers;
struct_decl->fields_fixed_size_bytes += type_size.fixed_size;
}
@@ -1020,9 +1081,9 @@ void ast_resolve(Ast *self, AstCompilerContext *context) {
/* TODO: Support other number types */
self->resolve_data.type.type = RESOLVED_TYPE_LHS_EXPR;
if(number->is_integer)
- self->resolve_data.type.value.lhs_expr = (LhsExpr*)context->compiler->default_types.i64;
+ self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.i64->lhs_expr;
else
- self->resolve_data.type.value.lhs_expr = (LhsExpr*)context->compiler->default_types.f64;
+ self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.f64->lhs_expr;
break;
}
case AST_FUNCTION_DECL:
@@ -1050,7 +1111,7 @@ void ast_resolve(Ast *self, AstCompilerContext *context) {
case AST_STRING:
/* TODO: Convert special combinations. For example \n to newline */
self->resolve_data.type.type = RESOLVED_TYPE_LHS_EXPR;
- self->resolve_data.type.value.lhs_expr = (LhsExpr*)context->compiler->default_types.str;
+ self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.str->lhs_expr;
break;
case AST_VARIABLE:
variable_resolve(self->value.variable, context, &self->resolve_data.type);