From: Brendan Hansen Date: Mon, 13 Jul 2020 03:21:54 +0000 (-0500) Subject: Fixed many bugs with type system; Ready to start pointers X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=def76246df5284094cfa28061b4a4b4eb8607f81;p=onyx.git Fixed many bugs with type system; Ready to start pointers --- diff --git a/include/onyxtypes.h b/include/onyxtypes.h index 5954d375..3f9a1094 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -48,7 +48,7 @@ typedef struct Type Type; #define TYPE_KINDS \ TYPE_KIND(Basic, TypeBasic) \ - TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) + TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) // TypePointer utilizes the elements of TypeBasic typedef enum TypeKind { Type_Kind_Invalid, @@ -85,5 +85,6 @@ extern Type basic_types[]; struct AstType; b32 types_are_compatible(Type* t1, Type* t2); Type* type_build_from_ast(bh_allocator alloc, struct AstType* type_node); +const char* type_get_name(Type* type); #endif // #ifndef ONYX_TYPES diff --git a/onyx b/onyx index 25b0e01d..81422df3 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/basic.onyx b/progs/basic.onyx index 3d3f1584..2ce18950 100644 --- a/progs/basic.onyx +++ b/progs/basic.onyx @@ -1,9 +1,17 @@ use "progs/intrinsics" +pointer_test :: proc { + p : ^i32 = 0 as ^i32; +} + +print :: foreign "host" "print" proc (val: i32) --- + test :: proc (a: bool) -> i32 { return 0; } export main :: proc { a : i32 = 0; + + print(a); } diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 38b9bac4..5b14f880 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -52,7 +52,8 @@ static void check_assignment(OnyxSemPassState* state, AstAssign* assign) { onyx_message_add(state->msgs, ONYX_MESSAGE_TYPE_ASSIGNMENT_TYPE_MISMATCH, assign->base.token->pos, - "TEMP", "TEMP"); + type_get_name(assign->lval->type), + type_get_name(assign->expr->type)); return; } } @@ -66,7 +67,8 @@ static void check_return(OnyxSemPassState* state, AstReturn* retnode) { onyx_message_add(state->msgs, ONYX_MESSAGE_TYPE_FUNCTION_RETURN_MISMATCH, retnode->expr->token->pos, - "TEMP", "TEMP"); + type_get_name(retnode->expr->type), + type_get_name(state->expected_return_type)); } } else { if (state->expected_return_type->Basic.size > 0) { @@ -81,7 +83,8 @@ static void check_return(OnyxSemPassState* state, AstReturn* retnode) { static void check_if(OnyxSemPassState* state, AstIf* ifnode) { check_expression(state, ifnode->cond); - if (ifnode->cond->type->kind != Type_Kind_Basic + if (ifnode->cond->type == NULL + || ifnode->cond->type->kind != Type_Kind_Basic || ifnode->cond->type->Basic.kind != Basic_Kind_Bool) { onyx_message_add(state->msgs, @@ -98,7 +101,8 @@ static void check_if(OnyxSemPassState* state, AstIf* ifnode) { static void check_while(OnyxSemPassState* state, AstWhile* whilenode) { check_expression(state, whilenode->cond); - if (whilenode->cond->type->kind != Type_Kind_Basic + if (whilenode->cond->type == NULL + || whilenode->cond->type->kind != Type_Kind_Basic || whilenode->cond->type->Basic.kind != Basic_Kind_Bool) { onyx_message_add(state->msgs, @@ -214,8 +218,9 @@ static void check_call(OnyxSemPassState* state, AstCall* call) { ONYX_MESSAGE_TYPE_FUNCTION_PARAM_TYPE_MISMATCH, actual_param->value->token->pos, callee->base.token->text, callee->base.token->length, - "TEMP", arg_pos, - "TEMP"); + type_get_name(formal_param->base.type), + arg_pos, + type_get_name(actual_param->base.type)); return; } @@ -262,7 +267,9 @@ static void check_binaryop(OnyxSemPassState* state, AstBinaryOp* binop) { } if (binop->left->type->kind == Type_Kind_Pointer - || binop->right->type->kind == Type_Kind_Pointer) { + || binop->right->type->kind == Type_Kind_Pointer + || (binop->left->type->Basic.flags & Basic_Flag_Pointer) + || (binop->right->type->Basic.flags & Basic_Flag_Pointer)) { onyx_message_add(state->msgs, ONYX_MESSAGE_TYPE_LITERAL, binop->base.token->pos, @@ -274,7 +281,8 @@ static void check_binaryop(OnyxSemPassState* state, AstBinaryOp* binop) { onyx_message_add(state->msgs, ONYX_MESSAGE_TYPE_BINOP_MISMATCH_TYPE, binop->base.token->pos, - "TEMP", "TEMP"); + type_get_name(binop->left->type), + type_get_name(binop->right->type)); return; } @@ -297,9 +305,12 @@ static void check_expression(OnyxSemPassState* state, AstTyped* expr) { break; case Ast_Kind_Unary_Op: + check_expression(state, ((AstUnaryOp *) expr)->expr); + if (((AstUnaryOp *) expr)->operation != Unary_Op_Cast) { - check_expression(state, ((AstUnaryOp *) expr)->expr); expr->type = ((AstUnaryOp *) expr)->expr->type; + } else { + expr->type = type_build_from_ast(state->node_allocator, expr->type_node); } break; @@ -368,21 +379,21 @@ static void check_global(OnyxSemPassState* state, AstGlobal* global) { ONYX_MESSAGE_TYPE_GLOBAL_TYPE_MISMATCH, global->base.token->pos, global->base.token->text, global->base.token->length, - "TEMP", "TEMP"); + type_get_name(global->base.type), + type_get_name(global->initial_value->type)); return; } } else { if (global->initial_value->type) global->base.type = global->initial_value->type; } + } - } else { - if (global->base.type == NULL) { - onyx_message_add(state->msgs, - ONYX_MESSAGE_TYPE_LITERAL, - global->base.token->pos, - "global variable with unknown type"); - } + if (global->base.type == NULL) { + onyx_message_add(state->msgs, + ONYX_MESSAGE_TYPE_LITERAL, + global->base.token->pos, + "global variable with unknown type"); } } @@ -455,6 +466,10 @@ static void check_function(OnyxSemPassState* state, AstFunction* func) { void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program) { + bh_arr_each(AstForeign *, foreign, program->foreigns) + if ((*foreign)->import->kind == Ast_Kind_Function) + check_function(state, (AstFunction *) (*foreign)->import); + bh_arr_each(AstGlobal *, global, program->globals) check_global(state, *global); diff --git a/src/onyxparser.c b/src/onyxparser.c index 3356c981..16598750 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -395,7 +395,8 @@ static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret) { AstType* type_node = NULL; // NOTE: var: type - if (parser->curr_token->type == Token_Type_Symbol) { + if (parser->curr_token->type != ':' + && parser->curr_token->type != '=') { type_node = parse_type(parser); } @@ -621,6 +622,7 @@ static AstType* parse_type(OnyxParser* parser) { while (1) { if (parser->curr_token->type == '^') { + parser_next_token(parser); AstPointerType* new = make_node(AstPointerType, Ast_Kind_Pointer_Type); *next_insertion = (AstType *) new; next_insertion = &new->elem; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 06e43044..fa72c348 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -324,6 +324,12 @@ void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program) { if (!symbol_unique_introduce(state, (*foreign)->import)) return; } + bh_arr_each(AstForeign *, foreign, program->foreigns) { + if ((*foreign)->import->kind == Ast_Kind_Function) { + symres_function(state, (AstFunction *) (*foreign)->import); + } + } + // NOTE: Then, resolve all symbols in all functions bh_arr_each(AstFunction *, function, program->functions) diff --git a/src/onyxtypes.c b/src/onyxtypes.c index f70a2710..1960b767 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -1,20 +1,20 @@ #include "onyxtypes.h" #include "onyxastnodes.h" +#include "onyxutils.h" -// NOTE: These have to be in the same order as Basiuc +// NOTE: These have to be in the same order as Basic Type basic_types[] = { { Type_Kind_Basic, { Basic_Kind_Void, 0, 0, "void" } }, { Type_Kind_Basic, { Basic_Kind_Bool, Basic_Flag_Boolean, 1, "bool" } }, { Type_Kind_Basic, { Basic_Kind_I8, Basic_Flag_Integer, 1, "i8" } }, - { Type_Kind_Basic, { Basic_Kind_I16, Basic_Flag_Integer, 2, "i16" } }, - { Type_Kind_Basic, { Basic_Kind_I32, Basic_Flag_Integer, 4, "i32" } }, - { Type_Kind_Basic, { Basic_Kind_I64, Basic_Flag_Integer, 8, "i64" } }, - { Type_Kind_Basic, { Basic_Kind_U8, Basic_Flag_Integer | Basic_Flag_Unsigned, 1, "u8" } }, + { Type_Kind_Basic, { Basic_Kind_I16, Basic_Flag_Integer, 2, "i16" } }, { Type_Kind_Basic, { Basic_Kind_U16, Basic_Flag_Integer | Basic_Flag_Unsigned, 2, "u16" } }, + { Type_Kind_Basic, { Basic_Kind_I32, Basic_Flag_Integer, 4, "i32" } }, { Type_Kind_Basic, { Basic_Kind_U32, Basic_Flag_Integer | Basic_Flag_Unsigned, 4, "u32" } }, + { Type_Kind_Basic, { Basic_Kind_I64, Basic_Flag_Integer, 8, "i64" } }, { Type_Kind_Basic, { Basic_Kind_U64, Basic_Flag_Integer | Basic_Flag_Unsigned, 8, "u64" } }, { Type_Kind_Basic, { Basic_Kind_F32, Basic_Flag_Float, 4, "f32" } }, @@ -27,6 +27,7 @@ b32 types_are_compatible(Type* t1, Type* t2) { // NOTE: If they are pointing to the same thing, // it is safe to assume they are the same type if (t1 == t2) return 1; + if (t1 == NULL || t2 == NULL) return 0; switch (t1->kind) { case Type_Kind_Basic: @@ -55,11 +56,12 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { switch (type_node->kind) { case Ast_Kind_Pointer_Type: { - TypePointer* ptr_type = bh_alloc_item(alloc, TypePointer); + Type* ptr_type = bh_alloc_item(alloc, Type); - ptr_type->base.flags |= Basic_Flag_Pointer; - ptr_type->base.size = 4; - ptr_type->elem = type_build_from_ast(alloc, ((AstPointerType *) type_node)->elem); + ptr_type->kind = Type_Kind_Pointer; + ptr_type->Pointer.base.flags |= Basic_Flag_Pointer; + ptr_type->Pointer.base.size = 4; + ptr_type->Pointer.elem = type_build_from_ast(alloc, ((AstPointerType *) type_node)->elem); return (Type *) ptr_type; } @@ -72,3 +74,13 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { return NULL; } } + +const char* type_get_name(Type* type) { + if (type == NULL) return "unknown"; + + switch (type->kind) { + case Type_Kind_Basic: return type->Basic.name; + case Type_Kind_Pointer: return bh_aprintf(global_scratch_allocator, "^%s", type_get_name(type->Pointer.elem)); + default: return "unknown"; + } +}