added: `conv.parse` and `Optional.flatten`
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 1 Jan 2024 21:25:01 +0000 (15:25 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 1 Jan 2024 21:25:01 +0000 (15:25 -0600)
core/container/optional.onyx
core/conv/parse.onyx
tests/stdlib/conv_parse [new file with mode: 0644]
tests/stdlib/conv_parse.onyx [new file with mode: 0644]

index 67041dc726b622499a28e0fc14806f19547f8ef7..c4bdd55133354c4cc1fc4bef62d874113d4e0f16 100644 (file)
@@ -61,6 +61,20 @@ use core
         *o = .{ Some = value };
     }
 
+    #doc "Flattens nested optionals."
+    // @Bug should be able to say ? ? $T here.
+    flatten :: (o1: ? Optional($T)) -> ? T {
+        switch o1 {
+            case o2: .Some {
+                return o2;
+            }
+
+            case .None ---
+        }
+
+        return .None;
+    }
+
     #doc "Monadic chaining operation."
     and_then :: (o: ?$T, transform: (T) -> ?$R) -> ?R {
         return switch o {
index 390509e4f703838d433ae6310b773b47ea5c3699..b4f65e6322bcf36ed57df1efd3884d3f92ad569a 100644 (file)
@@ -88,9 +88,16 @@ parse_any :: (target: rawptr, data_type: type_expr, to_parse: str, string_alloca
 
         case #default {
             if info.kind == .Enum {
-                // TEMPORARY this needs to look at the backing type for the
-                // enum in order to know how large this integer should be.
-                *cast(&u32) target = ~~ str_to_i64(to_parse);
+                val := str_to_i64(to_parse);
+                
+                einfo := info->as_enum();
+                switch einfo.backing_type {
+                    case i8,  u8  do *cast(&u8)  target = ~~val;
+                    case i16, u16 do *cast(&u16) target = ~~val;
+                    case i32, u32 do *cast(&u32) target = ~~val;
+                    case i64, u64 do *cast(&u64) target = ~~val;
+                }
+
                 return true;
             }
 
@@ -102,13 +109,41 @@ parse_any :: (target: rawptr, data_type: type_expr, to_parse: str, string_alloca
             if info.kind == .Union && union_constructed_from(data_type, Optional) {
                 parsed_successful := parse_any(memory.ptr_add(target, info.alignment), info->as_union().variants[1].type, to_parse, string_allocator);
                 if !parsed_successful {
-                    *cast(& u32) target = ~~ Optional(void).tag_enum.None;
+                    *cast(& u8) target = ~~ Optional(void).tag_enum.None;
                 } else {
-                    *cast(& u32) target = ~~ Optional(void).tag_enum.Some;
+                    *cast(& u8) target = ~~ Optional(void).tag_enum.Some;
                 }
+
+                return true;
             }
         }
     }
 
     return false;
 }
+
+
+#doc """
+    Shortcut to parse a type `T` using `parse_any`.
+"""
+parse :: ($T: type_expr, to_parse: str) -> ? T {
+    v: T;
+    if #this_package.parse_any(&v, to_parse) {
+        return v;
+    } else {
+        return .None;
+    }
+}
+
+#doc """
+    Shortcut to parse a type `T` using `parse_any`, and specify an allocator.
+"""
+parse_with_allocator :: ($T: type_expr, to_parse: str, allocator: Allocator) -> ? T {
+    v: T;
+    if #this_package.parse_any(&v, to_parse, allocator) {
+        return v;
+    } else {
+        return .None;
+    }
+}
+
diff --git a/tests/stdlib/conv_parse b/tests/stdlib/conv_parse
new file mode 100644 (file)
index 0000000..0646a55
--- /dev/null
@@ -0,0 +1,5 @@
+Some(1203)
+Some(45.3199)
+Some(72)
+Some(Coconut)
+[ Some(12), Some(34), Some(56), Some(78), Some(90) ]
diff --git a/tests/stdlib/conv_parse.onyx b/tests/stdlib/conv_parse.onyx
new file mode 100644 (file)
index 0000000..4eb3765
--- /dev/null
@@ -0,0 +1,21 @@
+use core {*}
+
+main :: () {
+    conv.parse(i32, "1203") |> println();
+    conv.parse(f32, "45.32") |> println();
+    conv.parse(? i8, "72") |> Optional.flatten() |> println();
+
+    conv.parse(Food, "2") |> println();
+
+    "12 34 56 78 90"
+    |> string.split_iter(" ")
+    |> iter.map(x => conv.parse(i32, x))
+    |> iter.collect()
+    |> println();
+}
+
+Food :: enum {
+    Apple;
+    Banana;
+    Coconut;
+}