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