-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework C++ Runtime Interval, IntervalSet, ATN and ATNState #1930
Changes from 10 commits
d7f5e18
21a53c2
0c0a929
d4b1869
7d36c5f
e70e412
b106f8e
5fd7a6e
156ecb6
0f6082e
3041b8e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,59 +26,56 @@ namespace misc { | |
ssize_t b; | ||
|
||
Interval(); | ||
explicit Interval(size_t a_, size_t b_); // For unsigned -> signed mappings. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I missed that one in my first review. Why did you remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Happy to put it back. However: I don't understand what you mean about
from compiling, and require:
instead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
will prevent both:
and will allow both:
What is the form you want to disallow? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's surprising. From my tests I found that the explicit constructor will be used for Anyway, the idea is simple: use the c-tor for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems we haven't finished this one. Are you sure we don't need the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't do what you think, re: signed vs. unsigned comparisons, however, adding it back in because it doesn't hurt. |
||
Interval(size_t a_, size_t b_); // For unsigned -> signed mappings. | ||
Interval(ssize_t a_, ssize_t b_); | ||
Interval(Interval const&) = default; | ||
virtual ~Interval(); | ||
Interval& operator=(Interval const&) = default; | ||
|
||
/// return number of elements between a and b inclusively. x..x is length 1. | ||
/// if b < a, then length is 0. 9..10 has length 2. | ||
virtual size_t length() const; | ||
size_t length() const; | ||
|
||
bool operator == (const Interval &other) const; | ||
|
||
virtual size_t hashCode() const; | ||
size_t hashCode() const; | ||
|
||
/// <summary> | ||
/// Does this start completely before other? Disjoint </summary> | ||
virtual bool startsBeforeDisjoint(const Interval &other) const; | ||
bool startsBeforeDisjoint(const Interval &other) const; | ||
|
||
/// <summary> | ||
/// Does this start at or before other? Nondisjoint </summary> | ||
virtual bool startsBeforeNonDisjoint(const Interval &other) const; | ||
bool startsBeforeNonDisjoint(const Interval &other) const; | ||
|
||
/// <summary> | ||
/// Does this.a start after other.b? May or may not be disjoint </summary> | ||
virtual bool startsAfter(const Interval &other) const; | ||
bool startsAfter(const Interval &other) const; | ||
|
||
/// <summary> | ||
/// Does this start completely after other? Disjoint </summary> | ||
virtual bool startsAfterDisjoint(const Interval &other) const; | ||
bool startsAfterDisjoint(const Interval &other) const; | ||
|
||
/// <summary> | ||
/// Does this start after other? NonDisjoint </summary> | ||
virtual bool startsAfterNonDisjoint(const Interval &other) const; | ||
bool startsAfterNonDisjoint(const Interval &other) const; | ||
|
||
/// <summary> | ||
/// Are both ranges disjoint? I.e., no overlap? </summary> | ||
virtual bool disjoint(const Interval &other) const; | ||
bool disjoint(const Interval &other) const; | ||
|
||
/// <summary> | ||
/// Are two intervals adjacent such as 0..41 and 42..42? </summary> | ||
virtual bool adjacent(const Interval &other) const; | ||
bool adjacent(const Interval &other) const; | ||
|
||
virtual bool properlyContains(const Interval &other) const; | ||
bool properlyContains(const Interval &other) const; | ||
|
||
/// <summary> | ||
/// Return the interval computed from combining this and other </summary> | ||
virtual Interval Union(const Interval &other) const; | ||
Interval Union(const Interval &other) const; | ||
|
||
/// <summary> | ||
/// Return the interval in common between this and o </summary> | ||
virtual Interval intersection(const Interval &other) const; | ||
Interval intersection(const Interval &other) const; | ||
|
||
virtual std::string toString() const; | ||
std::string toString() const; | ||
|
||
private: | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,54 +13,31 @@ | |
using namespace antlr4; | ||
using namespace antlr4::misc; | ||
|
||
IntervalSet const IntervalSet::COMPLETE_CHAR_SET = []() { | ||
IntervalSet complete = IntervalSet::of(Lexer::MIN_CHAR_VALUE, Lexer::MAX_CHAR_VALUE); | ||
complete.setReadOnly(true); | ||
return complete; | ||
}(); | ||
IntervalSet const IntervalSet::COMPLETE_CHAR_SET = | ||
IntervalSet::of(Lexer::MIN_CHAR_VALUE, Lexer::MAX_CHAR_VALUE); | ||
|
||
IntervalSet const IntervalSet::EMPTY_SET = []() { | ||
IntervalSet empty; | ||
empty.setReadOnly(true); | ||
return empty; | ||
}(); | ||
IntervalSet const IntervalSet::EMPTY_SET; | ||
|
||
IntervalSet::IntervalSet() { | ||
InitializeInstanceFields(); | ||
IntervalSet::IntervalSet() : _intervals() { | ||
} | ||
|
||
IntervalSet::IntervalSet(const std::vector<Interval> &intervals) : IntervalSet() { | ||
_intervals = intervals; | ||
IntervalSet::IntervalSet(const IntervalSet &set) : _intervals(set._intervals) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't like the changes to the c-tors. I took care to use delegating c-tors everywhere and want to stay with them, instead of repeating init of internal values over and over again. Please revert. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you insist. However: This a class with a single member that's being constructed empty and then assigned to in a constructor body. I don't see a repeated init here. What am I missing? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, this one is so simple, but I'd like to keep that pattern throughout the runtime. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you pls change this back also? As I said already, I like to stay with delegating c-tors. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK |
||
} | ||
|
||
IntervalSet::IntervalSet(const IntervalSet &set) : IntervalSet() { | ||
addAll(set); | ||
IntervalSet::IntervalSet(IntervalSet&& set) : IntervalSet(std::move(set._intervals)) { | ||
} | ||
|
||
IntervalSet::IntervalSet(int n, ...) : IntervalSet() { | ||
va_list vlist; | ||
va_start(vlist, n); | ||
|
||
for (int i = 0; i < n; i++) { | ||
add(va_arg(vlist, int)); | ||
} | ||
|
||
va_end(vlist); | ||
IntervalSet::IntervalSet(std::vector<Interval>&& intervals) : _intervals(std::move(intervals)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mentioned a replacement of the variadic variant with template params, but that's not it. So where is the new code? Also using Actually, the new code changes the semantic significantly. The variadic variant uses single value intervals (in fact it actually uses single elements, which are later converted to single element intervals). Your new code allows for any interval list (a case we already handled in a different c-tor). This change is not improving anything IMO. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The varadic code starts on line 42 of IntervalSet.h, but I think you found it from your later comment. The constructor that takes a vector rvalue reference is a private constructor used internally. If we want to use a constant here it will be local to this class and can be an explicit decision. Removing type-unsafe va_args code certainly seems like an improvement to me: The old code is likely to fail outright, especially on machines where sizeof(int) != sizeof(ssize_t). The new code is type-safe, provides compile-time diagnostics, and allows single and multi-value intervals. For the same arguments I don't see a semantic change (excluding failures because of va_args usage problems). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, I didn't ask for the variadic code, but the templated one (which I don't see in your patch). However, as you say, the new code is a private c-tor, which is not that obvious from the patch. I wonder, though, why you could remove the variadic code. Is it not used anywhere? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I replaced the varadic code with a templated version that is type safe and provides the same interface. There are two changes that are being mixed here because they're close by in the diff:
They are distinct changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My fault. I looked at the wrong places. The templated code is just fine (even though a bit less readable IMO). But type safety is a good thing. |
||
} | ||
|
||
IntervalSet::~IntervalSet() | ||
{ | ||
IntervalSet& IntervalSet::operator=(const IntervalSet& other) { | ||
_intervals = other._intervals; | ||
return *this; | ||
} | ||
|
||
IntervalSet& IntervalSet::operator=(const IntervalSet& other) | ||
{ | ||
if (_readonly) { | ||
throw IllegalStateException("can't alter read only IntervalSet"); | ||
} | ||
|
||
_intervals.clear(); | ||
|
||
return addAll(other); | ||
IntervalSet& IntervalSet::operator=(IntervalSet&& other) { | ||
_intervals = move(other._intervals); | ||
return *this; | ||
} | ||
|
||
IntervalSet IntervalSet::of(ssize_t a) { | ||
|
@@ -72,16 +49,10 @@ IntervalSet IntervalSet::of(ssize_t a, ssize_t b) { | |
} | ||
|
||
void IntervalSet::clear() { | ||
if (_readonly) { | ||
throw IllegalStateException("can't alter read only IntervalSet"); | ||
} | ||
_intervals.clear(); | ||
} | ||
|
||
void IntervalSet::add(ssize_t el) { | ||
if (_readonly) { | ||
throw IllegalStateException("can't alter read only IntervalSet"); | ||
} | ||
add(el, el); | ||
} | ||
|
||
|
@@ -90,10 +61,6 @@ void IntervalSet::add(ssize_t a, ssize_t b) { | |
} | ||
|
||
void IntervalSet::add(const Interval &addition) { | ||
if (_readonly) { | ||
throw IllegalStateException("can't alter read only IntervalSet"); | ||
} | ||
|
||
if (addition.b < addition.a) { | ||
return; | ||
} | ||
|
@@ -152,7 +119,7 @@ IntervalSet IntervalSet::Or(const std::vector<IntervalSet> &sets) { | |
|
||
IntervalSet& IntervalSet::addAll(const IntervalSet &set) { | ||
// walk set and add each interval | ||
for (auto &interval : set._intervals) { | ||
for (auto const& interval : set._intervals) { | ||
add(interval); | ||
} | ||
return *this; | ||
|
@@ -341,7 +308,7 @@ ssize_t IntervalSet::getMinElement() const { | |
return _intervals[0].a; | ||
} | ||
|
||
std::vector<Interval> IntervalSet::getIntervals() const { | ||
std::vector<Interval> const& IntervalSet::getIntervals() const { | ||
return _intervals; | ||
} | ||
|
||
|
@@ -518,10 +485,6 @@ void IntervalSet::remove(size_t el) { | |
} | ||
|
||
void IntervalSet::remove(ssize_t el) { | ||
if (_readonly) { | ||
throw IllegalStateException("can't alter read only IntervalSet"); | ||
} | ||
|
||
for (size_t i = 0; i < _intervals.size(); ++i) { | ||
Interval &interval = _intervals[i]; | ||
ssize_t a = interval.a; | ||
|
@@ -555,17 +518,3 @@ void IntervalSet::remove(ssize_t el) { | |
} | ||
} | ||
} | ||
|
||
bool IntervalSet::isReadOnly() const { | ||
return _readonly; | ||
} | ||
|
||
void IntervalSet::setReadOnly(bool readonly) { | ||
if (_readonly && !readonly) | ||
throw IllegalStateException("Can't alter readonly IntervalSet"); | ||
_readonly = readonly; | ||
} | ||
|
||
void IntervalSet::InitializeInstanceFields() { | ||
_readonly = false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh, that's still code from the automatic conversion. We don't need to create
std::string
here explicitly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this again -- The string conversion is from the existing code. I added the iterator check to avoid dereferencing a bad iterator in the debug code. That's a bugfix (if only in an error message).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My comment wasn't specifically for your patch. More loudly thinking... Would be nice if things like that get fixed while someone comes across them.