changed: `map.get` returns an Optional
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 22 Jun 2023 23:29:03 +0000 (18:29 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 22 Jun 2023 23:29:03 +0000 (18:29 -0500)
20 files changed:
core/container/map.onyx
core/conv/format.onyx
core/conv/parse.onyx
core/threads/thread.onyx
tests/aoc-2020/day15.onyx
tests/aoc-2020/day17.onyx
tests/aoc-2020/day20.onyx
tests/aoc-2020/day21.onyx
tests/aoc-2020/day24.onyx
tests/aoc-2020/day25.onyx
tests/aoc-2020/day7.onyx
tests/aoc-2021/day05.onyx
tests/aoc-2021/day08.onyx
tests/aoc-2021/day09.onyx
tests/aoc-2021/day10.onyx
tests/aoc-2021/day12.onyx
tests/aoc-2021/day14.onyx
tests/baked_parameters.onyx
tests/i32map.onyx
tests/persist_locals.onyx

index 594aa3e53cf6c31a132b5da87fcac5cecc670b1a..e055f4b4662d818975ab6b4aec6ed11e9aa21d28 100644 (file)
@@ -134,7 +134,7 @@ has :: (use map: &Map, key: map.Key_Type) -> bool {
     This is subject to change with the addition of Optional to the
     standard library.
 """
-get :: (use map: &Map, key: map.Key_Type) -> map.Value_Type {
+get :: (use map: &Map, key: map.Key_Type) -> map.Value_Type {
     lr := lookup(map, key);
     if lr.entry_index >= 0 do return entries[lr.entry_index].value;
 
@@ -301,7 +301,7 @@ as_iter :: (m: &Map) =>
 //
 // Helper operator overloads for accessing values, accessing
 // values by pointer, and setting values.
-#operator []  macro (map: Map($K, $V), key: K) ->      { return #this_package.get(&map, key); }
+#operator []  macro (map: Map($K, $V), key: K) -> ?V     { return #this_package.get(&map, key); }
 #operator &[] macro (map: Map($K, $V), key: K) -> &V     { return #this_package.get_ptr(&map, key); }
 #operator []= macro (map: Map($K, $V), key: K, value: V) { #this_package.put(&map, key, value); }
 
index 1f0eafd66b0765fe3c4b46f4fafd9042920aaa8c..91a66fa1ecb9f86187575ad1b02f39f13007f1b7 100644 (file)
@@ -433,9 +433,11 @@ format_any :: (output: &Format_Output, formatting: &Format, v: any) {
 
     //
     // Use a custom formatter, if one is registered for the type.
-    if formatting.custom_format && custom_formatters->has(v.type) {
-        custom_formatters[v.type](output, formatting, v.data);
-        return;
+    if formatting.custom_format {
+        custom_formatters->get(v.type)->with([formatter] {
+            formatter(output, formatting, v.data);
+            return;
+        });
     }
 
     switch v.type {
index 18dc22d02396c00687eaa2b5a7fcd62bed172211..c3e4b6f391e493df495afd755c0eee976dffd204 100644 (file)
@@ -20,9 +20,9 @@ parse_any :: macro (v: &$T, to_parse: str, string_allocator := context.allocator
 
 #overload
 parse_any :: (target: rawptr, data_type: type_expr, to_parse: str, string_allocator := context.allocator) -> bool {
-    if custom_parsers->has(data_type) {
-        return custom_parsers[data_type](target, to_parse, string_allocator);
-    }
+    custom_parsers->get(data_type)->with([parser] {
+        return parser(target, to_parse, string_allocator);
+    });
 
     use runtime.info {*};
     info := get_type_info(data_type);
index eaa9020780d271a24a9a86cb99ee8963e726f44a..caefd3e5702f1f40b83872f9a182ce8a2f2e24e3 100644 (file)
@@ -91,7 +91,7 @@ __initialize :: () {
 __exited :: (id: i32) {
     sync.scoped_mutex(&thread_mutex);
 
-    thread := thread_map->get(id);
+    thread := thread_map->get(id)?;
     if thread != null {
         thread.alive = false;
         #if runtime.Wait_Notify_Available {
index 6fa54b7f7c1e140df739007091218b531728529c..1bc2335c71e1e8a6ab955484ac24b65ee491050e 100644 (file)
@@ -26,12 +26,12 @@ main :: (args: [] cstr) {
     }
 
     while turn != 2021 {
-        st := map.get(&nums, last_num);
+        st := map.get(&nums, last_num) ?? .{};
 
         if st.previous == 0 do last_num = 0;
         else                do last_num = st.recent - st.previous;
 
-        st = map.get(&nums, last_num);
+        st = map.get(&nums, last_num) ?? .{};
         st.previous = st.recent;
         st.recent = turn;
         map.put(&nums, last_num, st);
index ccf9b0d1da8d94cb426e50e3cb3ca956558f9219..f1b5a87c1c25981f01ecf3cea3e6d25a0660b1d8 100644 (file)
@@ -43,8 +43,9 @@ get_neighbor_count :: (cubes: &Map(CubePos, CubeState), pos: CubePos) -> u32 {
     for x: -1 .. 2 do for y: -1 .. 2 do for z: -1 .. 2 do for w: -1 .. 2 {
         if x == 0 && y == 0 && z == 0 && w == 0 do continue;
         key := CubePos.{ pos.x + x, pos.y + y, pos.z + z, pos.w + w };
-        state := map.get(cubes, key);
-        if state.alive do count += 1;
+        map.get(cubes, key)->with([s] {
+            if s.alive do count += 1;
+        });
     }
 
     return count;
@@ -90,7 +91,7 @@ main :: (args: [] cstr) {
         }
 
         for &cube: cubes_to_consider {
-            state  := map.get(&cubes, *cube);
+            state  := map.get(&cubes, *cube) ?? .{};
             ncount := get_neighbor_count(&cubes, *cube);
             
             if state.alive {
@@ -103,7 +104,7 @@ main :: (args: [] cstr) {
         }
 
         for &cube: cubes_to_consider {
-            state := map.get(&cubes, *cube);
+            state := map.get(&cubes, *cube) ?? .{};
             state.alive = state.next;
             map.put(&cubes, *cube, state);
         }
index 99c983cc5c23883881b8e235882ceb730238c483..9ae73e7cd1f8b2eb89c24fc0a22dacc4b7ec2247 100644 (file)
@@ -332,7 +332,7 @@ main :: (args: [] cstr) {
 
         if grid[tid.pos_x + 12 * tid.pos_y] != 0 do continue;
         
-        tile_ptr := map.get(&tile_map, tid.match.tile);
+        tile_ptr := map.get(&tile_map, tid.match.tile)->unwrap();
         tile_ptr.pos_x = tid.pos_x;
         tile_ptr.pos_y = tid.pos_y;
         grid[tid.pos_x + 12 * tid.pos_y] = tid.match.tile;
@@ -348,7 +348,7 @@ main :: (args: [] cstr) {
     forest : [12 * 8 * 12 * 8] u8;
     for y: 0 .. 12 {
         for x: 0 .. 12 {
-            tile := map.get(&tile_map, grid[y * 12 + x]);
+            tile := map.get(&tile_map, grid[y * 12 + x])->unwrap();
 
             for fy: 0 .. 8 {
                 for fx: 0 .. 8 {
index 6a6ef029e5be70939d574651422e645583366eb4..729bbdd54d2e9537db7ea164470e58486143a887 100644 (file)
@@ -57,11 +57,10 @@ main :: (args: [] cstr) {
 
             array.push(&food.ingredients, ingredient_name);
 
-            ingredient := map.get(&ingredient_map, ingredient_name);
-            if ingredient.name.data == null {
-                ingredient.name = ingredient_name;
-                array.init(&ingredient.appears_on, 4);
-            }
+            ingredient := map.get(&ingredient_map, ingredient_name) ?? .{
+                name = ingredient_name,
+                appears_on = make([..] u32, 4)
+            };
 
             array.push(&ingredient.appears_on, line_num);
 
@@ -76,11 +75,10 @@ main :: (args: [] cstr) {
 
             array.push(&food.allergens, allergen_name);
 
-            allergen := map.get(&allergen_map, allergen_name);
-            if allergen.name.data == null {
-                allergen.name = allergen_name;
-                array.init(&allergen.appears_on, 4);
-            }
+            allergen := map.get(&allergen_map, allergen_name) ?? .{
+                name = allergen_name,
+                appears_on = make([..] u32, 4)
+            };
 
             array.push(&allergen.appears_on, line_num);
 
@@ -109,7 +107,7 @@ main :: (args: [] cstr) {
         potential_allergen_count := 0;
         for &allergen_name: potential_allergens {
             c := array_count_contains(&potential_allergens, *allergen_name, string.equal);
-            allergen := map.get(&allergen_map, *allergen_name)
+            allergen := map.get(&allergen_map, *allergen_name)->unwrap();
             if c == allergen.appears_on.count {
                 potential_allergen_count += 1;
             }
@@ -122,7 +120,7 @@ main :: (args: [] cstr) {
 
     total_safe := 0;
     for safe: definitely_safe {
-        ingredient := map.get(&ingredient_map, safe);
+        ingredient := map.get(&ingredient_map, safe)->unwrap();
         total_safe += ingredient.appears_on.count;
 
         map.delete(&ingredient_map, safe);
@@ -152,7 +150,7 @@ main :: (args: [] cstr) {
             }
 
             if match_count == 1 {
-                ingredient := map.get(&ingredient_map, matching_ingredient_name);
+                ingredient := map.get(&ingredient_map, matching_ingredient_name)->unwrap();
                 map.delete(&ingredient_map, matching_ingredient_name);
 
                 ingredient.allergen = allergen_entry.key;
index c77000305eaf06406eb416eab729c65ea9594b3e..d781376fd33d3524ab284a988282dd25b7e9acf9 100644 (file)
@@ -65,7 +65,7 @@ main :: (args: [] cstr) {
                }
 
 
-               curr := map.get(&grid, loc);
+               curr := map.get(&grid, loc) ?? .{};
                map.put(&grid, loc, .{ alive = !curr.alive });
        }
 
@@ -95,7 +95,7 @@ main :: (args: [] cstr) {
                }
 
                for &cell: cells_to_consider {
-                       state  := map.get(&grid, *cell);
+                       state  := map.get(&grid, *cell) ?? .{};
                        ncount := get_neighbor_count(&grid, *cell);
 
                        if state.alive {
@@ -125,7 +125,7 @@ get_neighbor_count :: (grid: &map.Map(Vec2, Cell), pos: Vec2) -> u32 {
        count := 0;
 
        for &dir: Hex_Directions {
-               cell := map.get(grid, Vec2.{ x = pos.x + dir.x, y = pos.y + dir.y });
+               cell := map.get(grid, Vec2.{ x = pos.x + dir.x, y = pos.y + dir.y }) ?? .{};
                if cell.alive do count += 1;
        }
 
index 2da20af980a54725fcca402250e21d0d33ae97b8..9b6f80b699eff6a10af9a93f8856237b598e2537 100644 (file)
@@ -35,7 +35,7 @@ dlp_bsgs :: (n: u32, a: u32, b: u32) -> u32 {
     tmp = ~~b;
     for i: 0 .. m {
         if map.has(&t, ~~tmp) {
-            v := map.get(&t, ~~tmp);
+            v := map.get(&t, ~~tmp) ?? 0;
             return i * m + v; 
         }
 
index cc03c7c9c6e95b53b35a4cb8c6c85d9c386faf40..5b030823c873a3b98589947a7997b38edf3d2a67 100644 (file)
@@ -32,7 +32,7 @@ bg_free :: (use graph: &BagGraph) {
 }
 
 bg_get_node :: (use graph: &BagGraph, name: str) -> &BagNode {
-    node := map.get(&node_map, name);
+    node := map.get(&node_map, name) ?? null;
 
     if node == null {
         node = calloc(sizeof BagNode);
index f87b06676256e14798506875c61c3384852170dd..cf34dc22ddae299888bd28ebb1156699dd71218b 100644 (file)
@@ -66,11 +66,7 @@ main :: (args) => {
 
         for &line: lines {
             for p: line_points(*line) {
-                if point_count->has(p) {
-                    point_count[p] = point_count[p] + 1;
-                } else {
-                    point_count[p] = 1;
-                }
+                point_count[p] = (point_count[p] ?? 0) + 1;
             }
         }
 
@@ -81,4 +77,4 @@ main :: (args) => {
 
         printf("Part 2: {}\n", count);
     }
-}
\ No newline at end of file
+}
index 2ea496974c0212ad1351658ca6a37c37994b9c81..ff2583575d75a6d5f1dc177117c58bd9b29f67f7 100644 (file)
@@ -74,8 +74,8 @@ decode_line :: (left, right: str) -> u32 {
 
     // Solve for bottom segment
     for three_data {
-        if solved_segments[it] == 4 do continue;
-        if solved_segments[it] == 1 do continue;
+        if solved_segments[it] ?? 0 == 4 do continue;
+        if solved_segments[it] ?? 0 == 1 do continue;
         for o: one_data do if it == o do continue continue;
 
         solved_segments[it] = 7;
@@ -88,7 +88,7 @@ decode_line :: (left, right: str) -> u32 {
         if seg.count != 5 do continue;
 
         for four_data {
-            if solved_segments[it] == 4 do continue;
+            if solved_segments[it] ?? 0 == 4 do continue;
             for o: one_data do if it == o do continue continue;
 
             if array.contains(seg, it) {
@@ -104,17 +104,17 @@ decode_line :: (left, right: str) -> u32 {
             break;
         }
 
-        if solved_segments[it] == 0 {
+        if solved_segments[it] ?? 0 == 0 {
             solved_segments[it] = 2;
         }
     }
 
     for one_data {
-        if solved_segments[it] == 0 do solved_segments[it] = 3;
+        if solved_segments[it] ?? 0 == 0 do solved_segments[it] = 3;
     }
 
     for *array.first(left_segments, (x) => x.count == 7)  {
-        if solved_segments[it] == 0 {
+        if solved_segments[it] ?? 0 == 0 {
             solved_segments[it] = 5;
         }
     }
@@ -126,7 +126,7 @@ decode_line :: (left, right: str) -> u32 {
         string.strip_whitespace(it);
         
         num_segments : [7] bool;
-        for w: *it do num_segments[solved_segments[w] - 1] = true;
+        for w: *it do num_segments[solved_segments[w] ?? 0 - 1] = true;
 
         sum *= 10;
         for i: 10 {
@@ -189,4 +189,4 @@ main :: (args) => {
 
         printf("Part {}: {}\n", 1 if PART == 1 else 2, answer);
     }
-}
\ No newline at end of file
+}
index 7a7eeed918bc41f1187425cd5f18f84177c4a314..1eb4e92dec115d5fa0ea0e91bf42976f8fb8954b 100644 (file)
@@ -36,12 +36,12 @@ find_span :: macro (low: Pos) -> u32 {
             potential << Pos.{t.x,t.y+1};
         }
         if t.x > 0 {
-            if heightmap[Pos.{t.x-1,t.y}].height > 0 {
+            if heightmap[Pos.{t.x-1,t.y}]->unwrap().height > 0 {
                 potential << Pos.{t.x-1,t.y};
             }
         }
         if t.y > 0 {
-            if heightmap[Pos.{t.x,t.y-1}].height > 0 {
+            if heightmap[Pos.{t.x,t.y-1}]->unwrap().height > 0 {
                 potential << Pos.{t.x,t.y-1};
             }
         }
@@ -85,12 +85,12 @@ main :: (args) => {
 
         for y: height - 1 do for x: width {
             map.update(&heightmap, .{x,y}) {
-                it.dy = it.height - heightmap[Pos.{x,y+1}].height;
+                it.dy = it.height - heightmap[Pos.{x,y+1}]->unwrap().height;
             }
         }
         for x: width - 1 do for y: height {
             map.update(&heightmap, .{x,y}) {
-                it.dx = it.height - heightmap[Pos.{x+1,y}].height;
+                it.dx = it.height - heightmap[Pos.{x+1,y}]->unwrap().height;
             }
         }
 
@@ -102,11 +102,11 @@ main :: (args) => {
             if y < height - 1 && h.dy >= 0 do continue;
 
             if x > 0 {
-                if heightmap[Pos.{x-1, y}].dx <= 0 do continue;
+                if heightmap[Pos.{x-1, y}]->unwrap().dx <= 0 do continue;
             }
 
             if y > 0 {
-                if heightmap[Pos.{x, y-1}].dy <= 0 do continue;
+                if heightmap[Pos.{x, y-1}]->unwrap().dy <= 0 do continue;
             }
 
             lowest << .{x, y};
index caa399cb883335d05ad74c37d7a9b7efea20c7f0..b64b9542b999e1b34e9c8668d1bb80e101181b74 100644 (file)
@@ -29,14 +29,14 @@ main :: (args) => {
             for ch: line {
                 switch ch {
                     case #char "(", #char "[", #char "<", #char "{" {
-                        char_stack << bracket_map[ch];
+                        char_stack << bracket_map[ch]->unwrap();
                     }
 
                     case #char ")", #char "]", #char ">", #char "}" {
                         x := array.pop(&char_stack);
                         if x != ch {
                             // printf("Expected '{}', found '{}' instead.\n", x, ch);
-                            corrupted_score += score_map[ch];
+                            corrupted_score += score_map[ch]->unwrap();
                             continue continue;
                         }
                     }
@@ -70,4 +70,4 @@ main :: (args) => {
         println(completion_scores);
         printf("Part 2: {}\n", completion_scores[completion_scores.count / 2]);
     }
-}
\ No newline at end of file
+}
index d253b7d74d42286623e47c19f6d9a68977300e8d..fe7d7a93b447fd49bf6d49bcfb6ba7542ab4045f 100644 (file)
@@ -67,7 +67,7 @@ main :: (args) => {
             node_idx := node_stack.count - 1;
             defer node_stack[node_idx].child_idx += 1;
 
-            children := edge_map[node_stack[node_idx].name];
+            children := edge_map[node_stack[node_idx].name] ?? .[];
             valid := node_stack[node_idx].child_idx < children.count;
 
             if valid {
index faf3452e20aff608f4299b584c226b8d2883d589..64362d380b68b38fff910784c50f4ad31f109db8 100644 (file)
@@ -78,7 +78,7 @@ main :: (args) => {
 
         mode: Map(u8, u64);
         for& polymer_state.entries {
-            mode[it.key.second] = mode[it.key.second] + it.value.now;
+            mode[it.key.second] = (mode[it.key.second] ?? .{}) + it.value.now;
         }
 
         maximum := array.fold(mode.entries, cast(u64) 0, (x, y) => math.max(x.value, y));
index d7b7bfc05faa56b48178df0cd2416b729c0e737f..459f032e36b799fcd27ee75444abfe3eb6929612 100644 (file)
@@ -39,7 +39,7 @@ main :: (args: [] cstr) {
     map.put(&ages, "Pam", 24);
 
     print_age :: (ages: &map.Map(str, u32), name: str) {
-        age := map.get(ages, name);
+        age := map.get(ages, name) ?? 0;
         printf("{}'s age is {}.\n", name, age);
     }
 
index 1c2cb03efaa38f86ad2b992f8518ec39fe014f84..fdc163682580c4ace344d7de48ee20261d8d7bd6 100644 (file)
@@ -17,7 +17,7 @@ main :: (args: [] cstr) {
     println(map.has(&imap, 50));
     println(map.has(&imap, 51));
 
-    printf("{}{}\n", map.get(&imap, 50), map.get(&imap, 1234));
+    printf("{}{}\n", map.get(&imap, 50)->unwrap(), map.get(&imap, 1234)->unwrap());
 
     printf("{*p}\n", &imap);
 
index 27b134d2b66df5e61564116e1d96e91e7ef06c63..2cf4da09938a5b1b340996d07957961b9a635c80 100644 (file)
@@ -32,7 +32,7 @@ cached_fib :: (n: u64) -> u64 {
 
     if n <= 1 do return n;
 
-    if map.has(&cache, n) do return map.get(&cache, n);
+    map.get(&cache, n)->with([n] { return n; });
 
     res := cached_fib(n - 1) + cached_fib(n - 2);
     map.put(&cache, n, res);