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