various improvements to any utilities
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 1 Nov 2022 03:12:15 +0000 (22:12 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 1 Nov 2022 03:12:15 +0000 (22:12 -0500)
compiler/src/astnodes.c
core/misc/any_utils.onyx
core/std.onyx
core/string/char_utils.onyx [new file with mode: 0644]

index e09c9402359b477288495ebd6b31721648630ad3..a1c15386ec45b36ae8f02e157045dee2237a0b8b 100644 (file)
@@ -1188,7 +1188,9 @@ b32 cast_is_legal(Type* from_, Type* to_, char** err_msg) {
 b32 implicit_cast_to_bool(AstTyped **pnode) {
     AstTyped *node = *pnode;
 
-    if (node->type->kind == Type_Kind_Pointer) {
+    if ((node->type->kind == Type_Kind_Basic &&
+        node->type->Basic.kind == Basic_Kind_Rawptr)
+        || (node->type->kind == Type_Kind_Pointer)) {
         AstNumLit *zero = make_int_literal(context.ast_alloc, 0);
         zero->type = &basic_types[Basic_Kind_Rawptr];
 
index 84b51f7f735ca27d78ac7a83f867e352dde2fbb5..5355145489d3a02519e38dc43192e5d761295571 100644 (file)
@@ -4,10 +4,15 @@ use runtime.info {
     get_type_info,
     Type_Info_Pointer,
     Type_Info_Struct,
+    Type_Info_Array,
+    Type_Info_Slice,
+    Type_Info_Dynamic_Array,
 
     get_struct_member
 }
 
+use core { iter, array }
+
 to_any :: macro (x: ^$T) => any.{x, T};
 
 any_as :: (a: any, $T: type_expr) -> ^T {
@@ -15,17 +20,32 @@ any_as :: (a: any, $T: type_expr) -> ^T {
     return cast(^T) a.data;
 }
 
-any_deference :: (v: any) -> any {
+// Dereference an pointer any.
+any_dereference :: (v: any) -> any {
     t := get_type_info(v.type);
     if t.kind == .Pointer {
         p := cast(^Type_Info_Pointer) t;
         return any.{*cast(^rawptr) v.data, p.to};
     }
 
-    return .{null, void};
+    return v;
+}
+
+// Subscript an array-like any.
+any_subscript :: (v: any, index: i32) -> any {
+    base_ptr, elem_type, count := any_as_array(v);
+    if index >= count || index < 0 {
+        return .{ null, void };
+    }
+
+    return any.{
+        cast(^u8) base_ptr + get_type_info(elem_type).size * index,
+        elem_type
+    };
 }
 
-any_get_member :: (v: any, member_name: str) -> any {
+// Select a member from an any.
+any_selector :: (v: any, member_name: str) -> any {
     t := get_type_info(v.type);
     if t.kind == .Struct {
         member := get_struct_member(v.type, member_name);
@@ -40,7 +60,7 @@ any_get_member :: (v: any, member_name: str) -> any {
 any_to_map :: (v: any) -> (Map(str, any), success: bool) {
     vals := v;
     if get_type_info(vals.type).kind == .Pointer {
-        vals = any_deference(vals);
+        vals = any_dereference(vals);
     }
 
     val_info := cast(^Type_Info_Struct) get_type_info(vals.type);
@@ -50,9 +70,57 @@ any_to_map :: (v: any) -> (Map(str, any), success: bool) {
 
     out: Map(str, any);
     for ^ val_info.members {
-        out->put(it.name, any_get_member(vals, it.name));
+        out->put(it.name, any_selector(vals, it.name));
     }
 
     return out, true;
 }
 
+// Creates an iterator out of an array-like any.
+any_iter :: (arr: any) -> Iterator(any) {
+    base_ptr, elem_type, count := any_as_array(arr);
+    if count == 0 {
+        return .{ null, ((_) => any.{}, false) };
+    }
+
+    return iter.generator(
+        ^.{
+            base_ptr  = base_ptr,
+            elem_type = elem_type,
+            elem_size = get_type_info(elem_type).size,
+            count     = count,
+            index     = 0,
+        },
+
+        (ctx: $T) -> (any, bool) {
+            if ctx.index < ctx.count {
+                defer ctx.index += 1;
+                return any.{ cast(^u8) ctx.base_ptr + ctx.elem_size * ctx.index, ctx.elem_type }, true;
+            }
+
+            return .{}, false;
+        }
+    );
+}
+
+
+#local
+any_as_array :: (arr: any) -> (rawptr, type_expr, u32) {
+    info := get_type_info(arr.type);
+
+    switch info.kind {
+        case .Array {
+            a := cast(^Type_Info_Array) info;
+            return arr.data, a.of, a.count;
+        }
+
+        case .Slice, .Dynamic_Array, .Variadic_Argument {
+            a := cast(^array.Untyped_Array) arr.data;
+            return a.data, (cast(^Type_Info_Dynamic_Array) info).of, a.count;
+        }
+
+        case #default {
+            return null, void, 0;
+        }
+    }
+}
index 76e445cabfda157775618f9a174f13fb4e0dbf15..0b2329a64b52c361d6430b5233bf6b324874f7e4 100644 (file)
@@ -21,6 +21,7 @@ package core
 #load "./string"
 #load "./string/reader"
 #load "./string/buffer"
+#load "./string/char_utils"
 
 #load "./intrinsics/onyx"
 #load "./intrinsics/wasm"
diff --git a/core/string/char_utils.onyx b/core/string/char_utils.onyx
new file mode 100644 (file)
index 0000000..e66669e
--- /dev/null
@@ -0,0 +1,18 @@
+package core.string
+
+#inject u8 {
+    is_alpha :: (c: u8) -> bool {
+        return (c >= #char "A" && c <= #char "Z")
+            || (c >= #char "a" && c <= #char "z");
+    }
+
+    is_num :: (c: u8) -> bool {
+        return (c >= #char "0" && c <= #char "9");
+    }
+
+    is_alphanum :: (c: u8) -> bool {
+        return c->is_alpha() || c->is_num();
+    }
+}
+
+