#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,
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
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);
}
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;
}
}
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) {
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,
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,
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;
}
}
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,
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;
}
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;
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");
}
}
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);
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);
}
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;
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)
#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" } },
// 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:
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;
}
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";
+ }
+}