diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-05-07 12:07:35 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-05-07 12:07:35 -0400 |
| commit | 818a0a26291cf456cfaa955401b1aa8219737d6c (patch) | |
| tree | 9eac0aacdcc41c718a18c98f3513beffaaeac2d3 /src/range_set.cpp | |
| parent | 29beb603b752928184f5f5e9f7479412de1e1951 (diff) | |
| download | zig-818a0a26291cf456cfaa955401b1aa8219737d6c.tar.gz zig-818a0a26291cf456cfaa955401b1aa8219737d6c.zip | |
switch expression - add compile errors
* for duplicate integer value
* for missing integer values
* for missing else prong
see #43
Diffstat (limited to 'src/range_set.cpp')
| -rw-r--r-- | src/range_set.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/range_set.cpp b/src/range_set.cpp new file mode 100644 index 0000000000..6158f52a00 --- /dev/null +++ b/src/range_set.cpp @@ -0,0 +1,81 @@ +#include "range_set.hpp" + +AstNode *rangeset_add_range(RangeSet *rs, BigNum *first, BigNum *last, AstNode *source_node) { + 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 ((bignum_cmp_gte(first, &range->first) && bignum_cmp_lte(first, &range->last)) || + (bignum_cmp_gte(last, &range->first) && bignum_cmp_lte(last, &range->last))) + { + return range_with_src->source_node; + } + } + rs->src_range_list.append({{*first, *last}, source_node}); + + return nullptr; + +} + +static bool add_range(ZigList<Range> *list, Range *new_range, BigNum *one) { + for (size_t i = 0; i < list->length; i += 1) { + Range *range = &list->at(i); + + BigNum first_minus_one; + if (bignum_sub(&first_minus_one, &range->first, one)) + zig_unreachable(); + + if (bignum_cmp_eq(&new_range->last, &first_minus_one)) { + range->first = new_range->first; + return true; + } + + BigNum last_plus_one; + if (bignum_add(&last_plus_one, &range->last, one)) + zig_unreachable(); + + if (bignum_cmp_eq(&new_range->first, &last_plus_one)) { + range->last = new_range->last; + return true; + } + } + list->append({new_range->first, new_range->last}); + return false; +} + +bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *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; + + 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}); + } + + BigNum one; + bignum_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); + } + + if (cur_list->length != 1) + return false; + Range *range = &cur_list->at(0); + if (bignum_cmp_neq(&range->first, first)) + return false; + if (bignum_cmp_neq(&range->last, last)) + return false; + return true; +} |
