| ... | @@ -4,8 +4,12 @@ AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode * | ... | @@ -4,8 +4,12 @@ AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode * |
| 4 | for (size_t i = 0; i < rs->src_range_list.length; i += 1) { | 4 | for (size_t i = 0; i < rs->src_range_list.length; i += 1) { |
| 5 | RangeWithSrc *range_with_src = &rs->src_range_list.at(i); | 5 | RangeWithSrc *range_with_src = &rs->src_range_list.at(i); |
| 6 | Range *range = &range_with_src->range; | 6 | Range *range = &range_with_src->range; |
| 7 | if ((bigint_cmp(first, &range->first) != CmpLT && bigint_cmp(first, &range->last) != CmpGT) || | 7 | if ((bigint_cmp(first, &range->first) == CmpLT && bigint_cmp(last, &range->first) == CmpLT) || |
| 8 | (bigint_cmp(last, &range->first) != CmpLT && bigint_cmp(last, &range->last) != CmpGT)) | 8 | (bigint_cmp(first, &range->last) == CmpGT && bigint_cmp(last, &range->last) == CmpGT)) |
| | 9 | { |
| | 10 | // first...last is completely before/after `range` |
| | 11 | } |
| | 12 | else |
| 9 | { | 13 | { |
| 10 | return range_with_src->source_node; | 14 | return range_with_src->source_node; |
| 11 | } | 15 | } |
| ... | @@ -16,64 +20,52 @@ AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode * | ... | @@ -16,64 +20,52 @@ AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode * |
| 16 | | 20 | |
| 17 | } | 21 | } |
| 18 | | 22 | |
| 19 | static bool add_range(ZigList<Range> *list, Range *new_range, BigInt *one) { | 23 | static int compare_rangeset(const void *a, const void *b) { |
| 20 | for (size_t i = 0; i < list->length; i += 1) { | 24 | const Range *r1 = &static_cast<const RangeWithSrc*>(a)->range; |
| 21 | Range *range = &list->at(i); | 25 | const Range *r2 = &static_cast<const RangeWithSrc*>(b)->range; |
| 22 | | 26 | // Assume no two ranges overlap |
| 23 | BigInt first_minus_one; | 27 | switch (bigint_cmp(&r1->first, &r2->first)) { |
| 24 | bigint_sub(&first_minus_one, &range->first, one); | 28 | case CmpLT: return -1; |
| 25 | | 29 | case CmpGT: return 1; |
| 26 | if (bigint_cmp(&new_range->last, &first_minus_one) == CmpEQ) { | 30 | case CmpEQ: return 0; |
| 27 | range->first = new_range->first; | 31 | } |
| 28 | return true; | 32 | zig_unreachable(); |
| 29 | } | 33 | } |
| 30 | | | |
| 31 | BigInt last_plus_one; | | |
| 32 | bigint_add(&last_plus_one, &range->last, one); | | |
| 33 | | 34 | |
| 34 | if (bigint_cmp(&new_range->first, &last_plus_one) == CmpEQ) { | 35 | void rangeset_sort(RangeSet *rs) { |
| 35 | range->last = new_range->last; | 36 | if (rs->src_range_list.length > 1) { |
| 36 | return true; | 37 | qsort(rs->src_range_list.items, rs->src_range_list.length, |
| 37 | } | 38 | sizeof(RangeWithSrc), compare_rangeset); |
| 38 | } | 39 | } |
| 39 | list->append({new_range->first, new_range->last}); | | |
| 40 | return false; | | |
| 41 | } | 40 | } |
| 42 | | 41 | |
| 43 | bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last) { | 42 | bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last) { |
| 44 | ZigList<Range> cur_list_value = {0}; | 43 | rangeset_sort(rs); |
| 45 | ZigList<Range> other_list_value = {0}; | | |
| 46 | ZigList<Range> *cur_list = &cur_list_value; | | |
| 47 | ZigList<Range> *other_list = &other_list_value; | | |
| 48 | | 44 | |
| 49 | for (size_t i = 0; i < rs->src_range_list.length; i += 1) { | 45 | const Range *first_range = &rs->src_range_list.at(0).range; |
| 50 | RangeWithSrc *range_with_src = &rs->src_range_list.at(i); | 46 | if (bigint_cmp(&first_range->first, first) != CmpEQ) |
| 51 | Range *range = &range_with_src->range; | 47 | return false; |
| 52 | cur_list->append({range->first, range->last}); | 48 | |
| 53 | } | 49 | const Range *last_range = &rs->src_range_list.last().range; |
| | 50 | if (bigint_cmp(&last_range->last, last) != CmpEQ) |
| | 51 | return false; |
| 54 | | 52 | |
| 55 | BigInt one; | 53 | BigInt one; |
| 56 | bigint_init_unsigned(&one, 1); | 54 | bigint_init_unsigned(&one, 1); |
| 57 | | 55 | |
| 58 | bool changes_made = true; | 56 | // Make sure there are no holes in the first...last range |
| 59 | while (changes_made) { | 57 | for (size_t i = 1; i < rs->src_range_list.length; i++) { |
| 60 | changes_made = false; | 58 | const Range *range = &rs->src_range_list.at(i).range; |
| 61 | for (size_t cur_i = 0; cur_i < cur_list->length; cur_i += 1) { | 59 | const Range *prev_range = &rs->src_range_list.at(i - 1).range; |
| 62 | Range *range = &cur_list->at(cur_i); | 60 | |
| 63 | changes_made = add_range(other_list, range, &one) || changes_made; | 61 | assert(bigint_cmp(&prev_range->last, &range->first) == CmpLT); |
| 64 | } | 62 | |
| 65 | ZigList<Range> *tmp = cur_list; | 63 | BigInt last_plus_one; |
| 66 | cur_list = other_list; | 64 | bigint_add(&last_plus_one, &prev_range->last, &one); |
| 67 | other_list = tmp; | 65 | |
| 68 | other_list->resize(0); | 66 | if (bigint_cmp(&last_plus_one, &range->first) != CmpEQ) |
| | 67 | return false; |
| 69 | } | 68 | } |
| 70 | | 69 | |
| 71 | if (cur_list->length != 1) | | |
| 72 | return false; | | |
| 73 | Range *range = &cur_list->at(0); | | |
| 74 | if (bigint_cmp(&range->first, first) != CmpEQ) | | |
| 75 | return false; | | |
| 76 | if (bigint_cmp(&range->last, last) != CmpEQ) | | |
| 77 | return false; | | |
| 78 | return true; | 70 | return true; |
| 79 | } | 71 | } |