Added adding and subtracting from pointers with C style pointer arithmetic
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 2 Aug 2020 20:08:14 +0000 (15:08 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 2 Aug 2020 20:08:14 +0000 (15:08 -0500)
include/onyxtypes.h
onyx
progs/alloc.onyx
progs/alloc_test.onyx
src/onyxchecker.c
src/onyxtypes.c

index 12d06a7546936cdf7e1b4be8eb52854a6b3a92cd..f997d89786b6838c013fa330f485df8bdbb93d93 100644 (file)
@@ -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 c72c7889fac77d065f72b2c5533253b5ba912ca2..913537647da248638c18e07a94171b53b945872a 100755 (executable)
Binary files a/onyx and b/onyx differ
index 56fdf7ef1960597d03b745ff4d10597d4bbf0da2..e2dac415531d6adb1b3c3c2b993c5c9a1a750641 100644 (file)
@@ -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;
index e5cf6d5ba93a4613e0644700e58da44bbb879550..9b2c7cd4a3ecfd0d25c34bc4803078375baea1de 100644 (file)
@@ -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" {
index baea6318fc86bc7cc7fbd4c3af4b1d11eac0c8e3..cfc3afd7328b8f15a1402b1173ebdac3a3a55bc8 100644 (file)
@@ -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;
 }
 
index 467b91aba352db88cc49d9e07d0a925f813cc506..c6891d4f46c6b0e8c5f5daf341f68809b5a35b80 100644 (file)
@@ -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)