diff options
| author | LemonBoy <thatlemon@gmail.com> | 2019-09-23 11:14:36 +0200 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-09-23 16:13:28 -0400 |
| commit | db988f42a7ac1ce0ec65fde0e7ea94009b1d7238 (patch) | |
| tree | 540a7ffaffbb430b9b8e440c06f9ebbcb5fef06e /src/range_set.cpp | |
| parent | 53ae03ebe9e0aa56bca1c9219a47d124b0435258 (diff) | |
| download | zig-db988f42a7ac1ce0ec65fde0e7ea94009b1d7238.tar.gz zig-db988f42a7ac1ce0ec65fde0e7ea94009b1d7238.zip | |
Fix computation of switch coverage
Closes #3258
Diffstat (limited to 'src/range_set.cpp')
| -rw-r--r-- | src/range_set.cpp | 90 |
1 files changed, 41 insertions, 49 deletions
diff --git a/src/range_set.cpp b/src/range_set.cpp index 83f34d505a..fd0076191b 100644 --- a/src/range_set.cpp +++ b/src/range_set.cpp @@ -4,8 +4,12 @@ AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode * for (size_t i = 0; i < rs->src_range_list.length; i += 1) { RangeWithSrc *range_with_src = &rs->src_range_list.at(i); Range *range = &range_with_src->range; - if ((bigint_cmp(first, &range->first) != CmpLT && bigint_cmp(first, &range->last) != CmpGT) || - (bigint_cmp(last, &range->first) != CmpLT && bigint_cmp(last, &range->last) != CmpGT)) + if ((bigint_cmp(first, &range->first) == CmpLT && bigint_cmp(last, &range->first) == CmpLT) || + (bigint_cmp(first, &range->last) == CmpGT && bigint_cmp(last, &range->last) == CmpGT)) + { + // first...last is completely before/after `range` + } + else { return range_with_src->source_node; } @@ -16,64 +20,52 @@ AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode * } -static bool add_range(ZigList<Range> *list, Range *new_range, BigInt *one) { - for (size_t i = 0; i < list->length; i += 1) { - Range *range = &list->at(i); - - BigInt first_minus_one; - bigint_sub(&first_minus_one, &range->first, one); - - if (bigint_cmp(&new_range->last, &first_minus_one) == CmpEQ) { - range->first = new_range->first; - return true; - } - - BigInt last_plus_one; - bigint_add(&last_plus_one, &range->last, one); +static int compare_rangeset(const void *a, const void *b) { + const Range *r1 = &static_cast<const RangeWithSrc*>(a)->range; + const Range *r2 = &static_cast<const RangeWithSrc*>(b)->range; + // Assume no two ranges overlap + switch (bigint_cmp(&r1->first, &r2->first)) { + case CmpLT: return -1; + case CmpGT: return 1; + case CmpEQ: return 0; + } + zig_unreachable(); +} - if (bigint_cmp(&new_range->first, &last_plus_one) == CmpEQ) { - range->last = new_range->last; - return true; - } +void rangeset_sort(RangeSet *rs) { + if (rs->src_range_list.length > 1) { + qsort(rs->src_range_list.items, rs->src_range_list.length, + sizeof(RangeWithSrc), compare_rangeset); } - list->append({new_range->first, new_range->last}); - return false; } bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last) { - ZigList<Range> cur_list_value = {0}; - ZigList<Range> other_list_value = {0}; - ZigList<Range> *cur_list = &cur_list_value; - ZigList<Range> *other_list = &other_list_value; + rangeset_sort(rs); - for (size_t i = 0; i < rs->src_range_list.length; i += 1) { - RangeWithSrc *range_with_src = &rs->src_range_list.at(i); - Range *range = &range_with_src->range; - cur_list->append({range->first, range->last}); - } + const Range *first_range = &rs->src_range_list.at(0).range; + if (bigint_cmp(&first_range->first, first) != CmpEQ) + return false; + + const Range *last_range = &rs->src_range_list.last().range; + if (bigint_cmp(&last_range->last, last) != CmpEQ) + return false; BigInt one; bigint_init_unsigned(&one, 1); - bool changes_made = true; - while (changes_made) { - changes_made = false; - for (size_t cur_i = 0; cur_i < cur_list->length; cur_i += 1) { - Range *range = &cur_list->at(cur_i); - changes_made = add_range(other_list, range, &one) || changes_made; - } - ZigList<Range> *tmp = cur_list; - cur_list = other_list; - other_list = tmp; - other_list->resize(0); + // Make sure there are no holes in the first...last range + for (size_t i = 1; i < rs->src_range_list.length; i++) { + const Range *range = &rs->src_range_list.at(i).range; + const Range *prev_range = &rs->src_range_list.at(i - 1).range; + + assert(bigint_cmp(&prev_range->last, &range->first) == CmpLT); + + BigInt last_plus_one; + bigint_add(&last_plus_one, &prev_range->last, &one); + + if (bigint_cmp(&last_plus_one, &range->first) != CmpEQ) + return false; } - if (cur_list->length != 1) - return false; - Range *range = &cur_list->at(0); - if (bigint_cmp(&range->first, first) != CmpEQ) - return false; - if (bigint_cmp(&range->last, last) != CmpEQ) - return false; return true; } |
