diff options
Diffstat (limited to 'src/ast.c')
-rw-r--r-- | src/ast.c | 147 |
1 files changed, 126 insertions, 21 deletions
@@ -299,6 +299,7 @@ int funccall_init(FunctionCall *self, BufferView name, ArenaAllocator *allocator int structdecl_init(StructDecl *self, Scope *parent, ArenaAllocator *allocator) { self->fields_num_pointers = 0; self->fields_fixed_size_bytes = 0; + self->is_signed = bool_false; return scope_init(&self->body, parent, allocator); } @@ -346,9 +347,8 @@ int string_init(String *self, BufferView str) { return 0; } -void number_init(Number *self, i64 value, bool is_integer, BufferView code_ref) { - self->value.integer = value; - self->is_integer = is_integer; +void number_init(Number *self, AmalNumber *value, BufferView code_ref) { + self->value = *value; self->code_ref = code_ref; } @@ -659,7 +659,7 @@ static void assignmentexpr_resolve(Ast *ast, AstCompilerContext *context) { /* This also covers extern variables, since extern variables are always const */ /* TODO: var.field type expressions should also be checked */ if(is_lhs_const) { - compiler_print_error(context->compiler, ast_get_code_reference(self->lhs_expr).data, "Can't assign to a const value"); + compiler_print_error(context->compiler, ast_get_code_reference(self->lhs_expr).data, "Can't assign to a const variable"); throw(AST_ERR); } @@ -757,7 +757,31 @@ static bool is_function_arg_compatible_with_parameter(AstResolvedType *arg, Func function_parameter_is_vararg(param, context); } -static void verify_func_call_matches_func_signature(FunctionCall *func_call, FunctionSignature *func_sig, AstCompilerContext *context) { +/* Pointers, isize and usize are returned with size 4, as that is the smallest possible size for them */ +static int arithmetic_type_get_size(StructDecl *self) { + assert(sizeof(usize) >= 4 && "Make this work when size of pointer is less than 4"); + return self->fields_num_pointers * 4 + self->fields_fixed_size_bytes; +} + +static bool is_implicit_cast_possible(AstResolvedType *from, FunctionParameter *to, AstCompilerContext *context) { + if(from->type == RESOLVED_TYPE_LHS_EXPR && to->resolve_data.type.type == RESOLVED_TYPE_LHS_EXPR) { + LhsExpr *from_lhs_expr = from->value.lhs_expr; + LhsExpr *to_lhs_expr = to->resolve_data.type.value.lhs_expr; + assert(to_lhs_expr->rhs_expr && to_lhs_expr->rhs_expr->type == AST_STRUCT_DECL); + /* TODO: Optimize, dont use is_arithmetic_type */ + if(is_arithmetic_type(from_lhs_expr, context->compiler) && is_arithmetic_type(to_lhs_expr, context->compiler)) { + StructDecl *from_struct_type = from_lhs_expr->rhs_expr->value.struct_decl; + StructDecl *to_struct_type = to_lhs_expr->rhs_expr->value.struct_decl; + assert(from_lhs_expr->rhs_expr->type == AST_STRUCT_DECL); + /* TODO: Also allow implicit cast if @from variable is const and if the const value can be cast to @to without data loss */ + /* TODO: Allow cast between signed<->unsigned if the value is known at compile-time and if it can be cast without data loss */ + return arithmetic_type_get_size(from_struct_type) <= arithmetic_type_get_size(to_struct_type) && from_struct_type->is_signed == to_struct_type->is_signed; + } + } + return bool_false; +} + +static void funccall_resolve_signature_types(FunctionCall *func_call, FunctionSignature *func_sig, AstCompilerContext *context) { Ast **arg = buffer_begin(&func_call->args); Ast **arg_end = buffer_end(&func_call->args); @@ -771,11 +795,18 @@ static void verify_func_call_matches_func_signature(FunctionCall *func_call, Fun usize i = 0; for(; i < num_check; ++i) { if(!is_function_arg_compatible_with_parameter(&(*arg)->resolve_data.type, 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); + /* TODO: Cast data to larger size? */ + if(!is_implicit_cast_possible(&(*arg)->resolve_data.type, 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); + /* + TODO: Use arg as tokenizer reference, but the name is generated right now so it doesn't belong to the tokenizer; + so the reference cant be used. + */ + compiler_print_error(context->compiler, func_call->func.name.data, + "Can't implicitly 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; @@ -826,7 +857,7 @@ static void funccall_resolve(Ast *self, AstCompilerContext *context) { ast_resolve(*ast, context); } - verify_func_call_matches_func_signature(func_call, func_sig, context); + funccall_resolve_signature_types(func_call, func_sig, context); } static TypeSize variable_type_get_byte_size(VariableType *self) { @@ -1057,6 +1088,88 @@ TypeSize resolved_type_get_byte_size(AstResolvedType *self) { return type_size; } +static void signed_integer_resolve(Ast *self, AstCompilerContext *context) { + Number *number = self->value.number; + assert(number->value.type == AMAL_NUMBER_SIGNED_INTEGER); + switch(number->value.bits) { + case 8: + self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.i8->lhs_expr; + break; + case 16: + self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.i16->lhs_expr; + break; + case 32: + self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.i32->lhs_expr; + break; + case 64: + self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.i64->lhs_expr; + break; + default: { + compiler_print_error(context->compiler, ast_get_code_reference(self).data, "Currently only 8, 16, 32 and 64 bit integers are supported. TODO: Support arbitrary size integer"); + throw(AST_ERR); + break; + } + } +} + +static void unsigned_integer_resolve(Ast *self, AstCompilerContext *context) { + Number *number = self->value.number; + assert(number->value.type == AMAL_NUMBER_UNSIGNED_INTEGER); + switch(number->value.bits) { + case 8: + self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.u8->lhs_expr; + break; + case 16: + self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.u16->lhs_expr; + break; + case 32: + self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.u32->lhs_expr; + break; + case 64: + self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.u64->lhs_expr; + break; + default: { + compiler_print_error(context->compiler, ast_get_code_reference(self).data, "Currently only 8, 16, 32 and 64 bit integers are supported. TODO: Support arbitrary size integer"); + throw(AST_ERR); + break; + } + } +} + +static void float_resolve(Ast *self, AstCompilerContext *context) { + Number *number = self->value.number; + assert(number->value.type == AMAL_NUMBER_FLOAT); + switch(number->value.bits) { + case 32: + self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.f32->lhs_expr; + break; + case 64: + self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.f64->lhs_expr; + break; + default: { + compiler_print_error(context->compiler, ast_get_code_reference(self).data, "Currently only 32 and 64 bit floats are supported. TODO: Support arbitrary size float"); + throw(AST_ERR); + break; + } + } +} + +static void number_resolve(Ast *self, AstCompilerContext *context) { + Number *number = self->value.number; + self->resolve_data.type.type = RESOLVED_TYPE_LHS_EXPR; + switch(number->value.type) { + case AMAL_NUMBER_SIGNED_INTEGER: + signed_integer_resolve(self, context); + break; + case AMAL_NUMBER_UNSIGNED_INTEGER: + unsigned_integer_resolve(self, context); + break; + case AMAL_NUMBER_FLOAT: + float_resolve(self, context); + break; + } +} + void ast_resolve(Ast *self, AstCompilerContext *context) { assert(self); assert(context->parser); @@ -1090,17 +1203,9 @@ void ast_resolve(Ast *self, AstCompilerContext *context) { self->resolve_data.status = AST_RESOLVING; self->parser = context->parser; switch(self->type) { - case AST_NUMBER: { - Number *number; - number = self->value.number; - /* 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 = &context->compiler->default_types.i64->lhs_expr; - else - self->resolve_data.type.value.lhs_expr = &context->compiler->default_types.f64->lhs_expr; + case AST_NUMBER: + number_resolve(self, context); break; - } case AST_FUNCTION_DECL: funcdecl_resolve(self, context); break; |