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