| author | |
| committer | |
| log | abd06d8eab508319e5f7839c802f4a81d80a0025 |
| tree | 4c718b756e129b76477e1fa850343cfe8c9191cb |
| parent | e272c29c163538159eb81f60cb5da3d7ebe099f9 |
3 files changed, 16 insertions(+), 40 deletions(-)
BRANCH_TODO-21| ... | ... | @@ -38,27 +38,6 @@ Performance optimizations to look into: |
| 38 | 38 | * make decl references in ZIR be u32 indexes to the Decl dependencies array hash map |
| 39 | 39 | instead of duplicating *Decl entries in zir.Code. |
| 40 | 40 | |
| 41 | if (maybe_src) |previous_src| { | |
| 42 | return sema.mod.fail(&block.base, item.src, "duplicate switch value", .{}); | |
| 43 | // TODO notes "previous value is here" previous_src | |
| 44 | } | |
| 45 | ||
| 46 | const item = try sema.resolveInst(item_ref); | |
| 47 | const value = try sema.resolveConstValue(block, item.src, item); | |
| 48 | const maybe_src = try range_set.add(value, value, item.src); | |
| 49 | try sema.validateSwitchDupeValue(parent_block, maybe_src, item.src); | |
| 50 | ||
| 51 | ||
| 52 | const first = try sema.resolveInst(item_first); | |
| 53 | const last = try sema.resolveInst(item_last); | |
| 54 | const maybe_src = try range_set.add( | |
| 55 | try sema.resolveConstValue(block, range_first_src, first_casted), | |
| 56 | try sema.resolveConstValue(block, range_last_src, last_casted), | |
| 57 | item.src, | |
| 58 | ); | |
| 59 | }; | |
| 60 | ||
| 61 | ||
| 62 | 41 | const item = try sema.resolveInst(item_ref); |
| 63 | 42 | if ((try sema.resolveConstValue(block, item.src, item)).toBool()) { |
| 64 | 43 | true_count += 1; |
src/RangeSet.zig+14-17| ... | ... | @@ -7,8 +7,8 @@ const SwitchProngSrc = @import("AstGen.zig").SwitchProngSrc; |
| 7 | 7 | ranges: std.ArrayList(Range), |
| 8 | 8 | |
| 9 | 9 | pub const Range = struct { |
| 10 | start: Value, | |
| 11 | end: Value, | |
| 10 | first: Value, | |
| 11 | last: Value, | |
| 12 | 12 | src: SwitchProngSrc, |
| 13 | 13 | }; |
| 14 | 14 | |
| ... | ... | @@ -22,18 +22,15 @@ pub fn deinit(self: *RangeSet) void { |
| 22 | 22 | self.ranges.deinit(); |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | pub fn add(self: *RangeSet, start: Value, end: Value, src: SwitchProngSrc) !?SwitchProngSrc { | |
| 25 | pub fn add(self: *RangeSet, first: Value, last: Value, src: SwitchProngSrc) !?SwitchProngSrc { | |
| 26 | 26 | for (self.ranges.items) |range| { |
| 27 | if ((start.compare(.gte, range.start) and start.compare(.lte, range.end)) or | |
| 28 | (end.compare(.gte, range.start) and end.compare(.lte, range.end))) | |
| 29 | { | |
| 30 | // ranges overlap | |
| 31 | return range.src; | |
| 27 | if (last.compare(.gte, range.first) and first.compare(.lte, range.last)) { | |
| 28 | return range.src; // They overlap. | |
| 32 | 29 | } |
| 33 | 30 | } |
| 34 | 31 | try self.ranges.append(.{ |
| 35 | .start = start, | |
| 36 | .end = end, | |
| 32 | .first = first, | |
| 33 | .last = last, | |
| 37 | 34 | .src = src, |
| 38 | 35 | }); |
| 39 | 36 | return null; |
| ... | ... | @@ -41,17 +38,17 @@ pub fn add(self: *RangeSet, start: Value, end: Value, src: SwitchProngSrc) !?Swi |
| 41 | 38 | |
| 42 | 39 | /// Assumes a and b do not overlap |
| 43 | 40 | fn lessThan(_: void, a: Range, b: Range) bool { |
| 44 | return a.start.compare(.lt, b.start); | |
| 41 | return a.first.compare(.lt, b.first); | |
| 45 | 42 | } |
| 46 | 43 | |
| 47 | pub fn spans(self: *RangeSet, start: Value, end: Value) !bool { | |
| 44 | pub fn spans(self: *RangeSet, first: Value, last: Value) !bool { | |
| 48 | 45 | if (self.ranges.items.len == 0) |
| 49 | 46 | return false; |
| 50 | 47 | |
| 51 | 48 | std.sort.sort(Range, self.ranges.items, {}, lessThan); |
| 52 | 49 | |
| 53 | if (!self.ranges.items[0].start.eql(start) or | |
| 54 | !self.ranges.items[self.ranges.items.len - 1].end.eql(end)) | |
| 50 | if (!self.ranges.items[0].first.eql(first) or | |
| 51 | !self.ranges.items[self.ranges.items.len - 1].last.eql(last)) | |
| 55 | 52 | { |
| 56 | 53 | return false; |
| 57 | 54 | } |
| ... | ... | @@ -66,11 +63,11 @@ pub fn spans(self: *RangeSet, start: Value, end: Value) !bool { |
| 66 | 63 | // i starts counting from the second item. |
| 67 | 64 | const prev = self.ranges.items[i]; |
| 68 | 65 | |
| 69 | // prev.end + 1 == cur.start | |
| 70 | try counter.copy(prev.end.toBigInt(&space)); | |
| 66 | // prev.last + 1 == cur.first | |
| 67 | try counter.copy(prev.last.toBigInt(&space)); | |
| 71 | 68 | try counter.addScalar(counter.toConst(), 1); |
| 72 | 69 | |
| 73 | const cur_start_int = cur.start.toBigInt(&space); | |
| 70 | const cur_start_int = cur.first.toBigInt(&space); | |
| 74 | 71 | if (!cur_start_int.eq(counter.toConst())) { |
| 75 | 72 | return false; |
| 76 | 73 | } |
src/Sema.zig+2-2| ... | ... | @@ -2888,7 +2888,7 @@ fn validateSwitchRange( |
| 2888 | 2888 | // because we only have the switch AST node. Only if we know for sure we need to report |
| 2889 | 2889 | // a compile error do we resolve the full source locations. |
| 2890 | 2890 | const first_val = val: { |
| 2891 | if (last.value()) |val| { | |
| 2891 | if (first.value()) |val| { | |
| 2892 | 2892 | if (val.isUndef()) { |
| 2893 | 2893 | const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .first); |
| 2894 | 2894 | return sema.failWithUseOfUndef(block, src); |
| ... | ... | @@ -2899,7 +2899,7 @@ fn validateSwitchRange( |
| 2899 | 2899 | return sema.failWithNeededComptime(block, src); |
| 2900 | 2900 | }; |
| 2901 | 2901 | const last_val = val: { |
| 2902 | if (first.value()) |val| { | |
| 2902 | if (last.value()) |val| { | |
| 2903 | 2903 | if (val.isUndef()) { |
| 2904 | 2904 | const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .last); |
| 2905 | 2905 | return sema.failWithUseOfUndef(block, src); |