Simplify refinement implementation

Implement refinement naively by running the refining selector against
the original scope and constraining the valid matches to those that are
within the initial match. This approach removes the need to compose the
initial match and the refining match to produce a match that can be
yielded to the caller. More importantly, it removes the need to use the
initial match as a scope for the refinement, which makes the
implementation ignorant of valid scope types.
diff --git a/packages/selector/src/index.js b/packages/selector/src/index.js
index 86c6ef9..1017419 100644
--- a/packages/selector/src/index.js
+++ b/packages/selector/src/index.js
@@ -21,12 +21,14 @@
       const refiningSelector = createSelector(source.refinedBy);
 
       return async function* matchAll(scope) {
-        const matches = selector(scope);
-        for await (let match of matches) {
-          const refiningScope = matchAsScope(match);
-          const refiningMatches = refiningSelector(refiningScope);
-          for await (let refiningMatch of refiningMatches) {
-            yield composeMatches(refiningMatch, match);
+        for await (const match of selector(scope)) {
+          const start = match.index;
+          const end = start + match[0].length;
+
+          for await (const refiningMatch of refiningSelector(scope)) {
+            if (refiningMatch.index < start) continue;
+            if (refiningMatch.index + refiningMatch[0].length > end) continue;
+            yield refiningMatch;
           }
         }
       };
@@ -35,16 +37,3 @@
     return selector;
   };
 }
-
-function matchAsScope(match) {
-  return match[0];
-}
-
-function composeMatches(...matches) {
-  return matches.reverse().reduce((match, refiningMatch) => {
-    const refinedMatch = [...refiningMatch];
-    refinedMatch.index = match.index + refiningMatch.index;
-    refinedMatch.input = match.input;
-    return refinedMatch;
-  });
-}