JoinMatcher: refactor

.match() is only in JoinMatcher now; add two abstract methods which
implementations use to tell whether the number of cycles matched is enough and
whether we should continue running cycles.
MatcherContext: make .hasMismatched() return a boolean instead of a Boolean

That is an API change, sure, but a minimal one; it couldn't return null anyway.
More comments in context/matchers