From: Brendan Hansen Date: Mon, 1 Jan 2024 21:25:01 +0000 (-0600) Subject: added: `conv.parse` and `Optional.flatten` X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=a9b0bef469edbbae63691a20dc1332ca164f7396;p=onyx.git added: `conv.parse` and `Optional.flatten` --- diff --git a/core/container/optional.onyx b/core/container/optional.onyx index 67041dc7..c4bdd551 100644 --- a/core/container/optional.onyx +++ b/core/container/optional.onyx @@ -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 { diff --git a/core/conv/parse.onyx b/core/conv/parse.onyx index 390509e4..b4f65e63 100644 --- a/core/conv/parse.onyx +++ b/core/conv/parse.onyx @@ -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 index 00000000..0646a553 --- /dev/null +++ b/tests/stdlib/conv_parse @@ -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 index 00000000..4eb3765d --- /dev/null +++ b/tests/stdlib/conv_parse.onyx @@ -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; +}