aboutsummaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c147
1 files changed, 126 insertions, 21 deletions
diff --git a/src/ast.c b/src/ast.c
index 5336e1e..e18b906 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -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;