From: Brendan Hansen Date: Sun, 2 Aug 2020 20:08:14 +0000 (-0500) Subject: Added adding and subtracting from pointers with C style pointer arithmetic X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=2eeba262e7ac66eace3bbe2a74e0565c8bdddbc2;p=onyx.git Added adding and subtracting from pointers with C style pointer arithmetic --- diff --git a/include/onyxtypes.h b/include/onyxtypes.h index 12d06a75..f997d897 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -123,6 +123,7 @@ b32 type_is_pointer(Type* type); b32 type_is_array(Type* tyoe); b32 type_is_struct(Type* type); b32 type_is_bool(Type* type); +b32 type_is_integer(Type* type); b32 type_results_in_void(Type* type); #endif // #ifndef ONYX_TYPES diff --git a/onyx b/onyx index c72c7889..91353764 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/alloc.onyx b/progs/alloc.onyx index 56fdf7ef..e2dac415 100644 --- a/progs/alloc.onyx +++ b/progs/alloc.onyx @@ -112,9 +112,7 @@ heap_free :: proc (ptr: rawptr) { hb_ptr := cast(^heap_block) (cast(u32) ptr - sizeof heap_block); // DEBUGGING: Fills freed memory with 0's - for i: 0, hb_ptr.size { - (cast(^u8) ptr)[i] = cast(u8) 0; - } + // for i: 0, hb_ptr.size do (cast(^u8) ptr)[i] = cast(u8) 0; hb_ptr.next = heap_state.free_list; heap_state.free_list = hb_ptr; diff --git a/progs/alloc_test.onyx b/progs/alloc_test.onyx index e5cf6d5b..9b2c7cd4 100644 --- a/progs/alloc_test.onyx +++ b/progs/alloc_test.onyx @@ -5,13 +5,19 @@ use package memory use package printing deferred_example :: proc -> i32 { - arr := cast([] i32) malloc(sizeof [8] i32); - defer if cast(rawptr) arr != null do mfree(arr); + arr := cast([] i64) malloc(sizeof [8] i64); + if cast(rawptr) arr == null do return 0; + defer mfree(arr); - for i: 0, 8 do arr[i] = i * i; - for i: 0, 8 do print(arr[i]); + for i: 0, 8 do arr[i] = cast(i64) (i * i); - return arr[1] + arr[7]; + walker := cast(^i64) arr; + for _: 0, 8 { + print(*(walker + 2)); + walker += 1; + } + + return cast(i32) (arr[1] + arr[7]); } proc #export "main" { diff --git a/src/onyxchecker.c b/src/onyxchecker.c index baea6318..cfc3afd7 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -341,78 +341,88 @@ CHECK(call, AstCall* call) { return 0; } -CHECK(binaryop, AstBinaryOp* binop, b32 assignment_is_ok) { - if (check_expression(&binop->left)) return 1; - if (check_expression(&binop->right)) return 1; +CHECK(binop_assignment, AstBinaryOp* binop, b32 assignment_is_ok) { + if (!assignment_is_ok) { + onyx_message_add(Msg_Type_Literal, + binop->token->pos, + "assignment not valid in expression"); + return 1; + } - if (binop_is_assignment(binop)) { - if (!assignment_is_ok) { - onyx_message_add(Msg_Type_Literal, - binop->token->pos, - "assignment not valid in expression"); - return 1; - } + if (!is_lval((AstNode *) binop->left)) { + onyx_message_add(Msg_Type_Not_Lval, + binop->left->token->pos, + binop->left->token->text, binop->left->token->length); + return 1; + } - if (!is_lval((AstNode *) binop->left)) { - onyx_message_add(Msg_Type_Not_Lval, - binop->left->token->pos, - binop->left->token->text, binop->left->token->length); - return 1; - } + if ((binop->left->flags & Ast_Flag_Const) != 0 && binop->left->type != NULL) { + onyx_message_add(Msg_Type_Assign_Const, + binop->token->pos, + binop->left->token->text, binop->left->token->length); + return 1; + } - if ((binop->left->flags & Ast_Flag_Const) != 0 && binop->left->type != NULL) { - onyx_message_add(Msg_Type_Assign_Const, - binop->token->pos, - binop->left->token->text, binop->left->token->length); - return 1; - } + if (binop->right->type == NULL) { + onyx_message_add(Msg_Type_Unresolved_Type, + binop->token->pos, + binop->right->token->text, binop->right->token->length); + return 1; + } - if (binop->operation == Binary_Op_Assign) { - // NOTE: Raw assignment - if (binop->left->type == NULL) { - binop->left->type = binop->right->type; - } + if (binop->operation == Binary_Op_Assign) { + // NOTE: Raw assignment - } else { - // NOTE: +=, -=, ... - - AstBinaryOp* binop_node = onyx_ast_node_new( - semstate.node_allocator, - sizeof(AstBinaryOp), - Ast_Kind_Binary_Op); - - binop_node->token = binop->token; - binop_node->left = binop->left; - binop_node->right = binop->right; - binop_node->type = binop->right->type; - - if (binop->operation == Binary_Op_Assign_Add) binop_node->operation = Binary_Op_Add; - else if (binop->operation == Binary_Op_Assign_Minus) binop_node->operation = Binary_Op_Minus; - else if (binop->operation == Binary_Op_Assign_Multiply) binop_node->operation = Binary_Op_Multiply; - else if (binop->operation == Binary_Op_Assign_Divide) binop_node->operation = Binary_Op_Divide; - else if (binop->operation == Binary_Op_Assign_Modulus) binop_node->operation = Binary_Op_Modulus; - else if (binop->operation == Binary_Op_Assign_And) binop_node->operation = Binary_Op_And; - else if (binop->operation == Binary_Op_Assign_Or) binop_node->operation = Binary_Op_Or; - else if (binop->operation == Binary_Op_Assign_Xor) binop_node->operation = Binary_Op_Xor; - else if (binop->operation == Binary_Op_Assign_Shl) binop_node->operation = Binary_Op_Shl; - else if (binop->operation == Binary_Op_Assign_Shr) binop_node->operation = Binary_Op_Shr; - else if (binop->operation == Binary_Op_Assign_Sar) binop_node->operation = Binary_Op_Sar; - - binop->right = (AstTyped *) binop_node; - binop->operation = Binary_Op_Assign; - } + // NOTE: This is the 'type inference' system. Very stupid, but very easy. + // If a left operand has an unknown type, fill it in with the type of + // the right hand side. + if (binop->left->type == NULL) binop->left->type = binop->right->type; } else { - if (!binop_is_compare(binop) && - (type_is_pointer(binop->left->type) - || type_is_pointer(binop->right->type))) { - onyx_message_add(Msg_Type_Literal, - binop->token->pos, - "binary operations are not supported for pointers (yet)."); - return 1; - } + // NOTE: +=, -=, ... + + AstBinaryOp* binop_node = onyx_ast_node_new( + semstate.node_allocator, + sizeof(AstBinaryOp), + Ast_Kind_Binary_Op); + + binop_node->token = binop->token; + binop_node->left = binop->left; + binop_node->right = binop->right; + binop_node->type = binop->right->type; + + if (binop->operation == Binary_Op_Assign_Add) binop_node->operation = Binary_Op_Add; + else if (binop->operation == Binary_Op_Assign_Minus) binop_node->operation = Binary_Op_Minus; + else if (binop->operation == Binary_Op_Assign_Multiply) binop_node->operation = Binary_Op_Multiply; + else if (binop->operation == Binary_Op_Assign_Divide) binop_node->operation = Binary_Op_Divide; + else if (binop->operation == Binary_Op_Assign_Modulus) binop_node->operation = Binary_Op_Modulus; + else if (binop->operation == Binary_Op_Assign_And) binop_node->operation = Binary_Op_And; + else if (binop->operation == Binary_Op_Assign_Or) binop_node->operation = Binary_Op_Or; + else if (binop->operation == Binary_Op_Assign_Xor) binop_node->operation = Binary_Op_Xor; + else if (binop->operation == Binary_Op_Assign_Shl) binop_node->operation = Binary_Op_Shl; + else if (binop->operation == Binary_Op_Assign_Shr) binop_node->operation = Binary_Op_Shr; + else if (binop->operation == Binary_Op_Assign_Sar) binop_node->operation = Binary_Op_Sar; + + binop->right = (AstTyped *) binop_node; + binop->operation = Binary_Op_Assign; + + if (check_binaryop(binop_node, 0)) return 1; } + if (!types_are_compatible(binop->left->type, binop->right->type)) { + onyx_message_add(Msg_Type_Binop_Mismatch, + binop->token->pos, + type_get_name(binop->left->type), + type_get_name(binop->right->type)); + return 1; + } + + binop->type = &basic_types[Basic_Kind_Void]; + + return 0; +} + +CHECK(binaryop_compare, AstBinaryOp* binop) { if (binop->left->type == NULL) { onyx_message_add(Msg_Type_Unresolved_Type, binop->token->pos, @@ -427,7 +437,6 @@ CHECK(binaryop, AstBinaryOp* binop, b32 assignment_is_ok) { return 1; } - if (!types_are_compatible(binop->left->type, binop->right->type)) { onyx_message_add(Msg_Type_Binop_Mismatch, binop->token->pos, @@ -436,29 +445,128 @@ CHECK(binaryop, AstBinaryOp* binop, b32 assignment_is_ok) { return 1; } - if (binop->operation >= Binary_Op_Bool_And - && binop->operation <= Binary_Op_Bool_Or) { + binop->type = &basic_types[Basic_Kind_Bool]; + return 0; +} + +CHECK(binaryop_bool, AstBinaryOp* binop) { + if (binop->left->type == NULL) { + onyx_message_add(Msg_Type_Unresolved_Type, + binop->token->pos, + binop->left->token->text, binop->left->token->length); + return 1; + } - if (!type_is_bool(binop->left->type) || !type_is_bool(binop->right->type)) { + if (binop->right->type == NULL) { + onyx_message_add(Msg_Type_Unresolved_Type, + binop->token->pos, + binop->right->token->text, binop->right->token->length); + return 1; + } + + if (!type_is_bool(binop->left->type) || !type_is_bool(binop->right->type)) { + onyx_message_add(Msg_Type_Literal, + binop->token->pos, + "boolean operator expects boolean types for both operands"); + return 1; + } + + binop->type = &basic_types[Basic_Kind_Bool]; + return 0; +} + +CHECK(binaryop, AstBinaryOp* binop, b32 assignment_is_ok) { + if (check_expression(&binop->left)) return 1; + if (check_expression(&binop->right)) return 1; + + if (binop_is_assignment(binop)) return check_binop_assignment(binop, assignment_is_ok); + if (binop_is_compare(binop)) return check_binaryop_compare(binop); + if (binop->operation == Binary_Op_Bool_And + || binop->operation == Binary_Op_Bool_Or) + return check_binaryop_bool(binop); + + if (type_is_pointer(binop->right->type)) { + onyx_message_add(Msg_Type_Literal, + binop->token->pos, + "right side of binary operator is a pointer"); + return 1; + } + + if (binop->left->type->kind == Type_Kind_Basic + && binop->left->type->Basic.kind == Basic_Kind_Rawptr + && !binop_is_compare(binop)) { + onyx_message_add(Msg_Type_Literal, + binop->token->pos, + "cannot operate on a rawptr"); + return 1; + } + + b32 lptr = type_is_pointer(binop->left->type); + if (lptr && (binop->operation != Binary_Op_Add && binop->operation != Binary_Op_Minus)) { + onyx_message_add(Msg_Type_Literal, + binop->token->pos, + "this operator is not supported for these operands"); + return 1; + } + + if (binop->left->type == NULL) { + onyx_message_add(Msg_Type_Unresolved_Type, + binop->token->pos, + binop->left->token->text, binop->left->token->length); + return 1; + } + + if (binop->right->type == NULL) { + onyx_message_add(Msg_Type_Unresolved_Type, + binop->token->pos, + binop->right->token->text, binop->right->token->length); + return 1; + } + + if (lptr) { + if (!type_is_integer(binop->right->type)) { onyx_message_add(Msg_Type_Literal, - binop->token->pos, - "boolean operator expects boolean types for both operands"); + binop->right->token->pos, + "expected integer type"); return 1; } - binop->type = &basic_types[Basic_Kind_Bool]; + AstNumLit* numlit = onyx_ast_node_new( + semstate.node_allocator, + sizeof(AstNumLit), + Ast_Kind_NumLit); - } else if (binop->operation >= Binary_Op_Equal - && binop->operation <= Binary_Op_Greater_Equal) { - binop->type = &basic_types[Basic_Kind_Bool]; + numlit->token = binop->right->token; + numlit->type = binop->right->type; + numlit->value.i = type_size_of(binop->left->type->Pointer.elem); - } else if (binop_is_assignment(binop)) { - binop->type = &basic_types[Basic_Kind_Void]; + AstBinaryOp* binop_node = onyx_ast_node_new( + semstate.node_allocator, + sizeof(AstBinaryOp), + Ast_Kind_Binary_Op); - } else { + binop_node->token = binop->token; + binop_node->left = binop->right; + binop_node->right = (AstTyped *) numlit; + binop_node->type = binop->right->type; + binop_node->operation = Binary_Op_Multiply; + + if (check_binaryop(binop_node, 0)) return 1; + + binop->right = (AstTyped *) binop_node; binop->type = binop->left->type; + binop->right->type = binop->left->type; + } + + if (!types_are_compatible(binop->left->type, binop->right->type)) { + onyx_message_add(Msg_Type_Binop_Mismatch, + binop->token->pos, + type_get_name(binop->left->type), + type_get_name(binop->right->type)); + return 1; } + binop->type = binop->left->type; return 0; } diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 467b91ab..c6891d4f 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -471,6 +471,12 @@ b32 type_is_bool(Type* type) { return type != NULL && type->kind == Type_Kind_Basic && type->Basic.kind == Basic_Kind_Bool; } +b32 type_is_integer(Type* type) { + if (type->kind != Type_Kind_Basic) return 0; + + return type->Basic.kind >= Basic_Kind_I8 && type->Basic.kind <= Basic_Kind_U64; +} + b32 type_results_in_void(Type* type) { return (type == NULL) || (type->kind == Type_Kind_Basic && type->Basic.kind == Basic_Kind_Void)