added ptrmap.onyx; small bugfixes; changed rules about auto pointer conversions
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 1 Sep 2020 16:00:16 +0000 (11:00 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 1 Sep 2020 16:00:16 +0000 (11:00 -0500)
core/array.onyx
core/file.onyx
core/ptrmap.onyx [new file with mode: 0644]
core/std/js.onyx
core/std/wasi.onyx
core/string.onyx
onyx
progs/poly_test.onyx
src/onyxchecker.c
src/onyxtypes.c
src/onyxutils.c

index 2498d4a451d2ed4cb3975508f2e916b7809602e9..7717c0584befa792375931b526b0080434a0e6fd 100644 (file)
@@ -67,6 +67,13 @@ array_delete :: proc (arr: ^[..] $T, idx: u32) {
     arr.count -= 1;
 }
 
+array_fast_delete :: proc (arr: ^[..] $T, idx: u32) {
+    if idx >= arr.count do return;
+
+    arr.data[idx] = arr.data[arr.count - 1];
+    arr.count -= 1;
+}
+
 array_contains :: proc (arr: ^[..] $T, x: T) -> bool {
     for i: 0, arr.count do if arr.data[i] == x do return true;
     return false;
index 70ac2683900c82f2e6a5cb9a2c9424ee38bdc583..83ca71885f0477708a2546484785e0fdc758615b 100644 (file)
@@ -100,7 +100,7 @@ file_get_contents_from_file :: proc (file: File) -> string {
     fd_seek(file.fd, 0l, Whence.Set, ^dummy);
 
     dummy2: u32; 
-    buf := IOVec.{ cast(rawptr) data, size };
+    buf := IOVec.{ data, size };
     fd_pread(file.fd, IOVecArray.{ ^buf, 1 }, 0l, ^dummy2);
 
     fd_seek(file.fd, prev_loc, Whence.Set, ^dummy);
diff --git a/core/ptrmap.onyx b/core/ptrmap.onyx
new file mode 100644 (file)
index 0000000..e828771
--- /dev/null
@@ -0,0 +1,111 @@
+package core
+
+
+PtrMap :: struct {
+    hashes  : [..] i32;
+    entries : [..] PtrMapEntry;
+}
+
+PtrMapEntry :: struct {
+    key   : rawptr;
+    value : rawptr;
+
+    next  : i32;    
+}
+
+ptrmap_init :: proc (use pmap: ^PtrMap, hash_count: i32 = 16) {
+    array_init(^hashes, hash_count);
+    array_init(^entries, 4);
+
+    for i: 0, hash_count do array_push(^hashes, -1);
+}
+
+ptrmap_free :: proc (use pmap: ^PtrMap) {
+    array_free(^hashes);
+    array_free(^entries);
+}
+
+
+ptrmap_put :: proc (use pmap: ^PtrMap, key: rawptr, value: rawptr) {
+    lr := ptrmap_lookup(pmap, key);
+
+    if lr.entry_index >= 0 {
+        entries[lr.entry_index].value = value;
+        return;
+    }
+
+    array_push(^entries, PtrMapEntry.{
+        key = key,
+        value = value,
+        next = hashes[lr.hash_index],
+    });
+
+    hashes[lr.hash_index] = entries.count - 1;
+}
+
+ptrmap_has :: proc (use pmap: ^PtrMap, key: rawptr) -> bool {
+    lr := ptrmap_lookup(pmap, key);
+    return lr.entry_index >= 0;
+}
+
+ptrmap_get :: proc (use pmap: ^PtrMap, key: rawptr) -> rawptr {
+    lr := ptrmap_lookup(pmap, key);
+    if lr.entry_index >= 0 do return entries[lr.entry_index].value;
+
+    return null;
+}
+
+ptrmap_delete :: proc (use pmap: ^PtrMap, key: rawptr) {
+    lr := ptrmap_lookup(pmap, key);
+    if lr.entry_index < 0 do return;    
+
+    if lr.entry_prev < 0   do hashes[lr.hash_index] = entries[lr.entry_index].next;
+    else                   do hashes[lr.entry_prev] = entries[lr.entry_index].next;
+
+    if lr.entry_index == entries.count - 1 {
+        array_pop(^entries);
+        return;
+    }
+
+    array_fast_delete(^entries, lr.entry_index);
+    last := ptrmap_lookup(pmap, entries[lr.entry_index].key);
+    if last.entry_prev >= 0    do entries[last.entry_prev].next = lr.entry_index;
+    else                       do hashes[last.hash_index] = lr.entry_index;
+}
+
+ptrmap_clear :: proc (use pmap: ^PtrMap) {
+    for i: 0, hashes.count do hashes.data[i] = -1;
+    entries.count = 0;
+}
+
+
+
+//
+// Private symbols
+//
+
+#private
+PtrMapLookupResult :: struct {
+    hash_index  : i32 = -1;
+    entry_index : i32 = -1;
+    entry_prev  : i32 = -1;
+}
+
+#private
+ptrmap_lookup :: proc (use pmap: ^PtrMap, key: rawptr) -> PtrMapLookupResult {
+    lr := PtrMapLookupResult.{};
+
+    hash := cast(u32) 0xcbf29ce4 ^ cast(u32) key;
+
+    lr.hash_index = hash % hashes.count;
+    lr.entry_index = hashes[lr.hash_index];
+
+    while lr.entry_index >= 0 {
+        if entries[lr.entry_index].key == key do return lr;
+
+        lr.entry_prev = lr.entry_index;
+        lr.entry_index = entries[lr.entry_index].next;
+    }
+
+    return lr;
+}
\ No newline at end of file
index 8650a2a4c65833f4767d110dba18a4f4e79905a9..69b0473bf91287b015f71ae2554aacf59dbf2375 100644 (file)
@@ -7,6 +7,7 @@ use package builtin
 #include_file "core/intrinsics"
 #include_file "core/math"
 #include_file "core/memory"
+#include_file "core/ptrmap"
 #include_file "core/random"
 #include_file "core/stdio"
 #include_file "core/string"
index 518befb8929d138f96834ab1ed662b84ea69db32..0c8d9495150997c01825bbab249fa6771a90bc99 100644 (file)
@@ -8,6 +8,7 @@ use package builtin
 #include_file "core/intrinsics"
 #include_file "core/math"
 #include_file "core/memory"
+#include_file "core/ptrmap"
 #include_file "core/random"
 #include_file "core/stdio"
 #include_file "core/string"
index b81b62279edb2e5ac6001863a59b8a02f3a7d21f..3804ea356408552946123e318dad1eef90a44e5f 100644 (file)
@@ -222,7 +222,7 @@ i64_to_string :: proc (n_: i64, base: u64, buf: Buffer) -> string {
 
 string_builder_add_i64 :: proc (use sb: ^StringBuilder, n: i64, base := 10l) -> ^StringBuilder {
     buf : [256] u8;
-    s := i64_to_string(n, base, Buffer.{ cast(rawptr) buf, 256 });
+    s := i64_to_string(n, base, Buffer.{ cast(^void) buf, 256 });
     return string_builder_add_string(sb, s);
 }
 
diff --git a/onyx b/onyx
index 8f0b89377acc2682f23f7a5cbd81ac7ea1e815d2..708fe4561c3244026968b17a827fb697c16b5720 100755 (executable)
Binary files a/onyx and b/onyx differ
index de6a34f653d1917b2240f1df59ce272083245ccb..4d0dbafe9d802f29e9c32fc6375d6dfb40922e57 100644 (file)
@@ -63,7 +63,7 @@ soa_deinit :: proc (s: ^SOA) {
     array_free(^s.b);
 }
 
-main2 :: proc (args: [] cstring) {
+main :: proc (args: [] cstring) {
     s : SOA;
     soa_init(^s);
     defer soa_deinit(^s);
@@ -85,9 +85,37 @@ main2 :: proc (args: [] cstring) {
     print("After adding...\n");
     print_arr_details(^s.a);
     print_arr_details(^s.b);
-}
 
-main :: proc (args: [] cstring) {
+
+    map : PtrMap;
+    ptrmap_init(^map);
+    defer ptrmap_free(^map);
+
+    for i: 0, 100 do ptrmap_put(^map, ^s.a[i], ^s.b[i]);
+
+    print("Has ^a[20]? ");
+    print(ptrmap_has(^map, ^s.a[20]));
+    print("\n");
+
+    print("Has null? ");
+    print(ptrmap_has(^map, null));
+    print("\n");
+
+    print("Value at ^a[50]: ");
+    print(ptrmap_get(^map, ^s.a[50]));
+    print(" == ");
+    print(^s.b[50]);
+    print("\n");
+
+    print("Deleteing ^a[20]\n");
+    ptrmap_delete(^map, ^s.a[20]);
+    
+    print("Has ^a[20]? ");
+    print(ptrmap_has(^map, ^s.a[20]));
+    print("\n");
+}
+    
+main2 :: proc (args: [] cstring) {
     print(cast(u32) __heap_start, 16);
 
     iarr_backing : [32] i32;
@@ -163,7 +191,7 @@ main :: proc (args: [] cstring) {
     print_array(varr, "\n");
 
 
-    dummy := Dummy.{ data = calloc(sizeof [5] i32) };
+    dummy := Dummy.{ data = cast(^u32) calloc(sizeof [5] i32) };
     for i: 0, dummy.count do dummy.data[i] = i * 5;
 
     print_array(dummy);
index b80a47287c9a20a0e8833a0286138de0e3bd56ae..0d0dfe16a4cf68f09c9fcc87199e4d78b191b7bc 100644 (file)
@@ -48,13 +48,15 @@ b32 check_return(AstReturn* retnode) {
         if (!types_are_compatible(retnode->expr->type, semstate.expected_return_type)) {
             onyx_report_error(retnode->expr->token->pos,
                     "Expected to return a value of type '%s', returning value of type '%s'.",
-                    type_get_name(retnode->expr->type),
-                    type_get_name(semstate.expected_return_type));
+                    type_get_name(semstate.expected_return_type),
+                    type_get_name(retnode->expr->type));
             return 1;
         }
     } else {
         if (semstate.expected_return_type->Basic.size > 0) {
-            onyx_report_error(retnode->token->pos, "returning from non-void function without value");
+            onyx_report_error(retnode->token->pos,
+                "Returning from non-void function without value. Expected a value of type '%s'.",
+                type_get_name(semstate.expected_return_type));
             return 1;
         }
     }
@@ -524,11 +526,11 @@ b32 check_binop_assignment(AstBinaryOp* binop, b32 assignment_is_ok) {
         if (check_binaryop(&binop_node, 0)) return 1;
     }
 
-    if (!types_are_compatible(binop->left->type, binop->right->type)) {
+    if (!types_are_compatible(binop->right->type, binop->right->type)) {
         onyx_report_error(binop->token->pos,
                 "Cannot assign value of type '%s' to a '%s'.",
-                type_get_name(binop->left->type),
-                type_get_name(binop->right->type));
+                type_get_name(binop->right->type),
+                type_get_name(binop->left->type));
         return 1;
     }
 
@@ -564,11 +566,19 @@ b32 check_binaryop_compare(AstBinaryOp** pbinop) {
         return 1;
     }
 
-    if (!types_are_compatible(binop->left->type, binop->right->type)) {
+    // HACK: Since ^... to rawptr is a one way conversion, strip any pointers
+    // away so they can be compared as expected
+    Type* ltype = binop->left->type;
+    Type* rtype = binop->right->type;
+
+    if (ltype->kind == Type_Kind_Pointer) ltype = &basic_types[Basic_Kind_Rawptr];
+    if (rtype->kind == Type_Kind_Pointer) rtype = &basic_types[Basic_Kind_Rawptr];
+
+    if (!types_are_compatible(ltype, rtype)) {
         onyx_report_error(binop->token->pos,
                 "Cannot compare '%s' to '%s'.",
-                type_get_name(binop->left->type),
-                type_get_name(binop->right->type));
+                type_get_name(ltype),
+                type_get_name(rtype));
         return 1;
     }
 
@@ -770,7 +780,7 @@ b32 check_struct_literal(AstStructLiteral* sl) {
 
         if (!types_are_compatible(formal, (*actual)->type)) {
             onyx_report_error(sl->token->pos,
-                    "Mismatched types for %d%s member, expected '%s, got '%s'.",
+                    "Mismatched types for %d%s member, expected '%s', got '%s'.",
                     i, bh_num_suffix(i),
                     type_get_name(formal),
                     type_get_name((*actual)->type));
index beade717c09c7a70341c8dc62a9180ebdace17d0..040d26bd537f34d893d9c5367d959c4f031dbc55 100644 (file)
@@ -134,9 +134,6 @@ b32 types_are_compatible(Type* t1, Type* t2) {
                 return types_are_compatible(t1->Pointer.elem, t2->Pointer.elem);
             }
 
-            if (t2->kind == Type_Kind_Basic && t2->Basic.kind == Basic_Kind_Rawptr)
-                return 1;
-
             break;
         }
 
index 538cb06fd654ed1ce7d3d70b63014d4af0a620bd..67d91f72086e4e5a2647d22f806960e5c3730e8a 100644 (file)
@@ -445,6 +445,7 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo
         return bh_table_get(AstFunction *, pp->concrete_funcs, key_buf);
     }
 
+    Type* old_return_type = semstate.expected_return_type;
     semstate.curr_scope = pp->poly_scope;
 
     AstFunction* func = (AstFunction *) ast_clone(semstate.node_allocator, pp->base_func);
@@ -459,9 +460,11 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo
 
 has_error:
     onyx_report_error(pos, "Error in polymorphic procedure generated from this call site.");
+    semstate.expected_return_type = old_return_type;
     return NULL;
 
 no_errors:
+    semstate.expected_return_type = old_return_type;
 
     bh_arr_push(semstate.other_entities, ((Entity) {
         .type = Entity_Type_Function_Header,